Latest EFY, Fix Bugs, New Card Layout, Seek Bar Gradient, Improved Captions

This commit is contained in:
dragos-efy 2024-05-22 23:47:19 +03:00
commit 3eefcf528f
121 changed files with 6415 additions and 3901 deletions

View file

@ -10,6 +10,129 @@
<FooterComponent />
</template>
<script>
import NavBar from "./components/NavBar.vue";
import FooterComponent from "./components/FooterComponent.vue";
const darkModePreference = window.matchMedia("(prefers-color-scheme: dark)");
export default {
components: {
NavBar,
FooterComponent,
},
data() {
return {
theme: "dark",
};
},
mounted() {
this.setTheme();
darkModePreference.addEventListener("change", () => {
this.setTheme();
});
if ("indexedDB" in window) {
const request = indexedDB.open("piped-db", 6);
request.onupgradeneeded = ev => {
const db = request.result;
console.log("Upgrading object store.");
if (!db.objectStoreNames.contains("watch_history")) {
const store = db.createObjectStore("watch_history", { keyPath: "videoId" });
store.createIndex("video_id_idx", "videoId", { unique: true });
store.createIndex("id_idx", "id", { unique: true, autoIncrement: true });
}
if (ev.oldVersion < 2) {
const store = request.transaction.objectStore("watch_history");
store.createIndex("watchedAt", "watchedAt", { unique: false });
}
if (!db.objectStoreNames.contains("playlist_bookmarks")) {
const store = db.createObjectStore("playlist_bookmarks", { keyPath: "playlistId" });
store.createIndex("playlist_id_idx", "playlistId", { unique: true });
store.createIndex("id_idx", "id", { unique: true, autoIncrement: true });
}
if (!db.objectStoreNames.contains("channel_groups")) {
const store = db.createObjectStore("channel_groups", { keyPath: "groupName" });
store.createIndex("groupName", "groupName", { unique: true });
}
if (!db.objectStoreNames.contains("playlists")) {
const playlistStore = db.createObjectStore("playlists", { keyPath: "playlistId" });
playlistStore.createIndex("playlistId", "playlistId", { unique: true });
const playlistVideosStore = db.createObjectStore("playlist_videos", { keyPath: "videoId" });
playlistVideosStore.createIndex("videoId", "videoId", { unique: true });
}
// migration to fix an invalid previous length of channel ids: 11 -> 24
(async () => {
if (ev.oldVersion < 6) {
const subscriptions = await this.fetchSubscriptions();
const channelGroups = await this.getChannelGroups();
for (let group of channelGroups) {
for (let i = 0; i < group.channels.length; i++) {
const tooShortChannelId = group.channels[i];
const foundChannel = subscriptions.find(
channel => channel.url.substr(-11) == tooShortChannelId,
);
if (foundChannel) group.channels[i] = foundChannel.url.substr(-24);
}
this.createOrUpdateChannelGroup(group);
}
}
})();
};
request.onsuccess = e => {
window.db = e.target.result;
};
} else console.log("This browser doesn't support IndexedDB");
const App = this;
(async function () {
const defaultLang = await App.defaultLanguage;
const locale = App.getPreferenceString("hl", defaultLang);
if (locale !== App.TimeAgoConfig.locale) {
const localeTime = await import(`../node_modules/javascript-time-ago/locale/${locale}.json`)
.catch(() => null)
.then(module => module?.default);
if (localeTime) {
App.TimeAgo.addLocale(localeTime);
App.TimeAgoConfig.locale = locale;
}
}
if (window.i18n.global.locale.value !== locale) {
if (!window.i18n.global.availableLocales.includes(locale)) {
const messages = await import(`./locales/${locale}.json`).then(module => module.default);
window.i18n.global.setLocaleMessage(locale, messages);
}
window.i18n.global.locale.value = locale;
}
})();
},
methods: {
setTheme() {
let themePref = this.getPreferenceString("theme", "dark"); // dark, light or auto
const themes = {
dark: "dark",
light: "light",
auto: darkModePreference.matches ? "dark" : "light",
};
this.theme = themes[themePref];
this.changeTitleBarColor();
// Used for the scrollbar
const root = document.querySelector(":root");
this.theme === "dark" ? root.classList.add("dark") : root.classList.remove("dark");
},
changeTitleBarColor() {
const currentColor = { dark: "#0F0F0F", light: "#FFF" };
const themeColor = document.querySelector("meta[name='theme-color']");
themeColor.setAttribute("content", currentColor[this.theme]);
},
},
};
</script>
<style>
#app {
min-height: calc(var(--efy_100vh) - var(--efy_gap2));
@ -91,6 +214,12 @@ video {
}
.pp-video-card-buttons :is(a:not(.pp-color), button:not(.pp-color)) {
background: var(--efy_bg1);
&:has([class*="headphones"], [class*="circle-plus"]) {
aspect-ratio: 1;
}
i {
margin: 0;
}
}
.pp-video-card-buttons .pp-color {
color: var(--efy_text2);
@ -138,106 +267,103 @@ video {
:is(.pp-video-card-channel > a, .pp-video-card-channel > .pp-text):empty {
display: none;
}
i[class*="i-fa"] {
}
.cards_horizontal {
.pp-rec-vids {
grid-template-columns: 1fr 500rem;
}
.video-grid {
grid-template-columns: repeat(auto-fill, minmax(480rem, 1fr));
}
.video-card {
display: flex;
flex-direction: row;
.video_item_link {
img {
height: 100%;
border-radius: var(--efy_radius) 0 0 var(--efy_radius);
}
.pp-video-card-title,
.flex {
display: none !important;
}
.pp-time,
.pp-watched {
position: absolute;
padding: 2rem 8rem;
border: var(--efy_border);
border-radius: var(--efy_radius0);
}
.pp-time {
background: var(--efy_bg);
bottom: var(--efy_gap00);
left: var(--efy_gap00);
}
.pp-watched {
margin: 0;
bottom: var(--efy_gap00);
right: calc(var(--efy_gap00) + 4rem);
}
}
.pp-card-info {
display: flex;
flex-direction: column;
max-width: 200rem;
.pp-video-card-2 {
margin: 5rem 0;
}
.pp-video-card-title {
font-weight: bold;
}
.pp-video-card-buttons {
width: 100%;
display: flex;
flex-direction: row;
.pp-time,
.pp-watched {
display: none;
}
}
.pp-video-card-channel {
width: 100%;
display: flex;
margin-top: 0;
> .pp-text span {
max-width: 90rem;
}
}
}
}
}
.video-card.watched {
.video_item_link img {
filter: brightness(0.3) saturate(0) !important;
}
}
[efy_mode*="light"] .video-card.watched {
.video_item_link img {
filter: contrast(0.3) saturate(0) !important;
}
}
.cards_horizontal .watched_progress {
height: 100% !important;
width: 4rem !important;
bottom: calc(100% + 7rem) !important;
left: calc(100% - 4rem) !important;
div:nth-of-type(1) {
display: none;
}
div:nth-of-type(2) {
width: 4rem;
border-radius: var(--efy_radius) var(--efy_radius) 0 0;
background: var(--efy_color);
box-shadow: -3rem 0 5rem #0005;
}
}
body:not(.cards_horizontal) .pp-video-card-2 {
display: none;
}
</style>
<script>
import NavBar from "./components/NavBar.vue";
import FooterComponent from "./components/FooterComponent.vue";
const darkModePreference = window.matchMedia("(prefers-color-scheme: dark)");
export default {
components: {
NavBar,
FooterComponent,
},
data() {
return {
theme: "dark",
};
},
mounted() {
this.setTheme();
darkModePreference.addEventListener("change", () => {
this.setTheme();
});
if ("indexedDB" in window) {
const request = indexedDB.open("piped-db", 5);
request.onupgradeneeded = ev => {
const db = request.result;
console.log("Upgrading object store.");
if (!db.objectStoreNames.contains("watch_history")) {
const store = db.createObjectStore("watch_history", { keyPath: "videoId" });
store.createIndex("video_id_idx", "videoId", { unique: true });
store.createIndex("id_idx", "id", { unique: true, autoIncrement: true });
}
if (ev.oldVersion < 2) {
const store = request.transaction.objectStore("watch_history");
store.createIndex("watchedAt", "watchedAt", { unique: false });
}
if (!db.objectStoreNames.contains("playlist_bookmarks")) {
const store = db.createObjectStore("playlist_bookmarks", { keyPath: "playlistId" });
store.createIndex("playlist_id_idx", "playlistId", { unique: true });
store.createIndex("id_idx", "id", { unique: true, autoIncrement: true });
}
if (!db.objectStoreNames.contains("channel_groups")) {
const store = db.createObjectStore("channel_groups", { keyPath: "groupName" });
store.createIndex("groupName", "groupName", { unique: true });
}
if (!db.objectStoreNames.contains("playlists")) {
const playlistStore = db.createObjectStore("playlists", { keyPath: "playlistId" });
playlistStore.createIndex("playlistId", "playlistId", { unique: true });
const playlistVideosStore = db.createObjectStore("playlist_videos", { keyPath: "videoId" });
playlistVideosStore.createIndex("videoId", "videoId", { unique: true });
}
};
request.onsuccess = e => {
window.db = e.target.result;
};
} else console.log("This browser doesn't support IndexedDB");
const App = this;
(async function () {
const defaultLang = await App.defaultLanguage;
const locale = App.getPreferenceString("hl", defaultLang);
if (locale !== App.TimeAgoConfig.locale) {
const localeTime = await import(`../node_modules/javascript-time-ago/locale/${locale}.json`)
.catch(() => null)
.then(module => module?.default);
if (localeTime) {
App.TimeAgo.addLocale(localeTime);
App.TimeAgoConfig.locale = locale;
}
}
if (window.i18n.global.locale.value !== locale) {
if (!window.i18n.global.availableLocales.includes(locale)) {
const messages = await import(`./locales/${locale}.json`).then(module => module.default);
window.i18n.global.setLocaleMessage(locale, messages);
}
window.i18n.global.locale.value = locale;
}
})();
},
methods: {
setTheme() {
let themePref = this.getPreferenceString("theme", "dark");
if (themePref == "auto") this.theme = darkModePreference.matches ? "dark" : "light";
else this.theme = themePref;
// Change title bar color based on user's theme
const themeColor = document.querySelector("meta[name='theme-color']");
if (this.theme === "light") {
themeColor.setAttribute("content", "#FFF");
} else {
themeColor.setAttribute("content", "#0F0F0F");
}
// Used for the scrollbar
const root = document.querySelector(":root");
this.theme == "dark" ? root.classList.add("dark") : root.classList.remove("dark");
},
},
};
</script>

View file

@ -0,0 +1,80 @@
<template>
<ModalComponent @close="$emit('close')">
<div class="min-w-[50vw] flex flex-col">
<div class="h-[70vh] overflow-y-scroll pr-4">
<span v-t="'actions.add_to_group'" class="mb-3 inline-block w-max text-2xl" />
<div v-for="(group, index) in channelGroups" :key="group.groupName" class="px-1">
<div class="flex items-center justify-between">
<span>{{ group.groupName }}</span>
<input
type="checkbox"
:checked="group.channels.includes(channelId)"
@change="onCheckedChange(index, group)"
/>
</div>
<hr class="h-1 w-full" />
</div>
</div>
<button v-t="'actions.create_group'" class="btn ml-auto w-max" @click="showCreateGroupModal = true" />
</div>
</ModalComponent>
<CreateGroupModal
v-if="showCreateGroupModal"
:on-create-group="onCreateGroup"
@close="showCreateGroupModal = false"
/>
</template>
<script>
import ModalComponent from "./ModalComponent.vue";
import CreateGroupModal from "./CreateGroupModal.vue";
export default {
components: {
ModalComponent,
CreateGroupModal,
},
props: {
channelId: {
type: String,
required: true,
},
},
emits: ["close"],
data() {
return {
showCreateGroupModal: false,
channelGroups: [],
};
},
mounted() {
this.loadChannelGroups();
},
methods: {
async loadChannelGroups() {
const groups = await this.getChannelGroups();
this.channelGroups.push(...groups);
},
onCheckedChange(index, group) {
if (group.channels.includes(this.channelId)) {
group.channels.splice(index, 1);
} else {
group.channels.push(this.channelId);
}
this.createOrUpdateChannelGroup(group);
},
onCreateGroup(newGroupName) {
if (!newGroupName || this.channelGroups.some(group => group.groupName == newGroupName)) return;
const newGroup = {
groupName: newGroupName,
channels: [],
};
this.channelGroups.push(newGroup);
this.createOrUpdateChannelGroup(newGroup);
this.showCreateGroupModal = false;
},
},
};
</script>

View file

@ -1,35 +1,84 @@
<template>
<div class="flex flex-col efy_trans_filter efy_shadow_trans">
<div class="efy_trans_filter efy_shadow_trans flex flex-col">
<router-link
:to="props.item.url"
class="flex items-center p-[10rem] gap-[10rem]"
:to="item.url"
class="flex items-center gap-[10rem] p-[10rem]"
style="border-bottom: var(--efy_border)"
>
<img
class="efy_shadow_trans"
style="border-radius: var(--efy_radius); width: 40rem; aspect-ratio: 1"
:src="props.item.thumbnail"
:src="item.thumbnail"
loading="lazy"
width="40"
height="40"
/>
<div class="flex items-center overflow-hidden pp-text">
<p v-text="props.item.name" class="pp-video-card-title p-0!" />
<font-awesome-icon v-if="props.item.verified" class="ml-1.5" icon="check" />
<div class="pp-text flex items-center overflow-hidden">
<p class="pp-video-card-title p-0!" v-text="item.name" />
<i v-if="item.verified" class="i-fa6-solid:check ml-1.5" />
</div>
</router-link>
<div style="padding: 10rem">
<p v-if="props.item.description" v-text="props.item.description" />
<div v-if="props.item.videos >= 0" v-text="`${props.item.videos} ${$t('video.videos')}`" />
<p v-if="item.description" v-text="item.description" />
<div v-if="item.videos >= 0" v-text="`${item.videos} ${$t('video.videos')}`" />
</div>
<router-link v-if="item.uploaderUrl" class="link" :to="item.uploaderUrl">
<p>
<span v-text="item.uploader" />
<i v-if="item.uploaderVerified" class="i-fa6-solid:check ml-1.5" />
</p>
</router-link>
<a v-if="item.uploaderName" class="link" v-text="item.uploaderName" />
<template v-if="item.videos >= 0">
<br v-if="item.uploaderName" />
<strong v-text="`${item.videos} ${$t('video.videos')}`" />
</template>
<button
v-if="subscribed != null"
class="btn mt-2 w-max"
@click="subscribeHandler"
v-text="
$t('actions.' + (subscribed ? 'unsubscribe' : 'subscribe')) + ' - ' + numberFormat(item.subscribers)
"
/>
</div>
</template>
<script setup>
const props = defineProps({
item: {
type: Object,
required: true,
<script>
export default {
props: {
item: {
type: Object,
required: true,
},
},
});
data() {
return {
subscribed: null,
};
},
computed: {
channelId(_this) {
return _this.item.url.substr(-24);
},
},
mounted() {
this.updateSubscribedStatus();
},
methods: {
async updateSubscribedStatus() {
this.subscribed = await this.fetchSubscriptionStatus(this.channelId);
console.log(this.subscribed);
},
subscribeHandler() {
this.toggleSubscriptionState(this.channelId, this.subscribed).then(success => {
if (success) this.subscribed = !this.subscribed;
});
},
},
};
</script>

View file

@ -1,23 +1,38 @@
<template>
<ErrorHandler v-if="channel && channel.error" :message="channel.message" :error="channel.error" />
<div v-if="channel" v-show="!channel.error" class="mt-[15rem]">
<LoadingIndicatorPage :show-content="channel != null && !channel.error">
<img v-if="channel.bannerUrl" :src="channel.bannerUrl" class="w-full efy_shadow_trans" loading="lazy" />
<LoadingIndicatorPage :show-content="channel != null && !channel.error">
<img
v-if="channel.bannerUrl"
loading="lazy"
:src="channel.bannerUrl"
class="efy_shadow_trans mt-[15rem] w-full"
/>
<div class="flex flex-col">
<div class="pp-channel-page-author flex">
<img height="48" width="48" class="efy_shadow_trans" :src="channel.avatarUrl" />
<h5 v-text="channel.name" />
<font-awesome-icon v-if="channel.verified" class="ml-1.5" icon="check" />
<div class="flex items-center gap-1">
<h5 v-text="channel.name" />
<i v-if="channel.verified" class="i-fa6-solid:check ml-2" />
</div>
</div>
<p v-text="channel.description" style="margin: 10rem 0 0 0" />
<p style="margin: 10rem 0 0 0" v-text="channel.description" />
<div class="pp-channel-tabs">
<button
v-t="{
path: `actions.${subscribed ? 'unsubscribe' : 'subscribe'}`,
args: { count: numberFormat(channel.subscriberCount) },
}"
class="pp-subscribe"
@click="subscribeHandler"
v-text="
$t('actions.' + (subscribed ? 'unsubscribe' : 'subscribe')) +
' - ' +
numberFormat(channel.subscriberCount)
"
></button>
<button
v-if="subscribed"
v-t="'actions.add_to_group'"
class="btn"
@click="showGroupModal = true"
></button>
<!-- RSS Feed button -->
@ -31,7 +46,7 @@
class="pp-square"
style="display: inline; float: unset"
>
<font-awesome-icon icon="rss" />
<i class="i-fa6-solid:rss" />
</a>
<WatchOnButton :link="`https://youtube.com/channel/${channel.id}`" />
<p style="place-self: center">|</p>
@ -44,43 +59,33 @@
<span v-text="tab.translatedName"></span>
</button>
</div>
</div>
<hr />
<hr />
<div class="video-grid">
<ContentItem
v-for="item in contentItems"
:key="item.url"
:item="item"
height="94"
width="168"
hide-channel
class="efy_trans_filter"
/>
</div>
</LoadingIndicatorPage>
</div>
<div class="video-grid">
<ContentItem
v-for="item in contentItems"
:key="item.url"
:item="item"
height="94"
width="168"
hide-channel
class="efy_trans_filter"
/>
</div>
<AddToGroupModal v-if="showGroupModal" :channel-id="channel.id.substr(-24)" @close="showGroupModal = false" />
</LoadingIndicatorPage>
</template>
<style>
.pp-channel-tabs {
display: flex;
flex-wrap: wrap;
margin: 15rem 0;
gap: var(--efy_gap0);
}
.pp-channel-tabs :is(button, [role="button"]) {
margin: 0;
border: 0;
}
</style>
<script>
import ErrorHandler from "./ErrorHandler.vue";
import ContentItem from "./ContentItem.vue";
import WatchOnButton from "./WatchOnButton.vue";
import LoadingIndicatorPage from "./LoadingIndicatorPage.vue";
// import CollapsableText from "./CollapsableText.vue";
import AddToGroupModal from "./AddToGroupModal.vue";
export default {
components: {
@ -89,6 +94,7 @@ export default {
WatchOnButton,
LoadingIndicatorPage,
// CollapsableText,
AddToGroupModal,
},
data() {
return {
@ -97,6 +103,7 @@ export default {
tabs: [],
selectedTab: 0,
contentItems: [],
showGroupModal: false,
};
},
mounted() {
@ -116,24 +123,8 @@ export default {
methods: {
async fetchSubscribedStatus() {
if (!this.channel.id) return;
if (!this.authenticated) {
this.subscribed = this.isSubscribedLocally(this.channel.id);
return;
}
this.fetchJson(
this.authApiUrl() + "/subscribed",
{
channelId: this.channel.id,
},
{
headers: {
Authorization: this.getAuthToken(),
},
},
).then(json => {
this.subscribed = json.subscribed;
});
this.subscribed = await this.fetchSubscriptionStatus(this.channel.id);
},
async fetchChannel() {
const url = this.$route.path.includes("@")
@ -205,21 +196,9 @@ export default {
});
},
subscribeHandler() {
if (this.authenticated) {
this.fetchJson(this.authApiUrl() + (this.subscribed ? "/unsubscribe" : "/subscribe"), null, {
method: "POST",
body: JSON.stringify({
channelId: this.channel.id,
}),
headers: {
Authorization: this.getAuthToken(),
"Content-Type": "application/json",
},
});
} else {
if (!this.handleLocalSubscriptions(this.channel.id)) return;
}
this.subscribed = !this.subscribed;
this.toggleSubscriptionState(this.channel.id, this.subscribed).then(success => {
if (success) this.subscribed = !this.subscribed;
});
},
getTranslatedTabName(tabName) {
let translatedTabName = tabName;
@ -230,8 +209,8 @@ export default {
case "playlists":
translatedTabName = this.$t("titles.playlists");
break;
case "channels":
translatedTabName = this.$t("titles.channels");
case "albums":
translatedTabName = this.$t("titles.albums");
break;
case "shorts":
translatedTabName = this.$t("video.shorts");
@ -270,3 +249,16 @@ export default {
},
};
</script>
<style>
.pp-channel-tabs {
display: flex;
flex-wrap: wrap;
margin: 15rem 0 0 0;
gap: var(--efy_gap0);
}
.pp-channel-tabs :is(button, [role="button"]) {
margin: 0;
border: 0;
}
</style>

View file

@ -1,18 +1,18 @@
<template>
<div class="pp-chapters max-h-75vh">
<h6 class="title efy_trans_filter efy_shadow_trans">{{ $t("video.chapters") }} - {{ chapters.length }}</h6>
<h6 class="efy_trans_filter efy_shadow_trans title">{{ $t("video.chapters") }} - {{ chapters.length }}</h6>
<div
v-for="(chapter, index) in chapters"
:key="chapter.start"
class="chapter flex efy_anim_pulse"
class="chapter efy_anim_pulse flex"
:class="isCurrentChapter(index) ? 'pp-chapter-active' : 'efy_shadow_trans efy_trans_filter'"
@click="$emit('seek', chapter.start)"
>
<img :src="chapter.image" :alt="chapter.title" />
<span
:title="chapter.title"
v-text="timeFormat(chapter.start) + ' - ' + chapter.title"
class="text font-bold"
v-text="timeFormat(chapter.start) + ' - ' + chapter.title"
/>
</div>
</div>

View file

@ -1,9 +1,9 @@
<template v-if="text">
<div class="whitespace-pre-wrap">
<!-- eslint-disable-next-line vue/no-v-html -->
<span v-if="showFullText" v-html="fullText()" />
<span v-if="showFullText" class="contentText" v-html="fullText()" />
<!-- eslint-disable-next-line vue/no-v-html -->
<span v-else v-html="colapsedText()" />
<span v-else v-html="collapsedText()" />
<span v-if="text.length > visibleLimit && !showFullText">...</span>
<button
v-if="text.length > visibleLimit"
@ -44,9 +44,15 @@ export default {
fullText() {
return purifyHTML(rewriteDescription(this.text));
},
colapsedText() {
collapsedText() {
return purifyHTML(rewriteDescription(this.text.slice(0, this.visibleLimit)));
},
},
};
</script>
<style>
.contentText {
word-wrap: anywhere;
}
</style>

View file

@ -1,5 +1,5 @@
<template>
<div class="comment flex mt-1.5">
<div class="comment mt-1.5 flex">
<router-link style="height: fit-content" :to="comment.commentorUrl">
<img :src="comment.thumbnail" class="comment-avatar" height="48" width="48" loading="lazy" alt="Avatar" />
</router-link>
@ -7,7 +7,7 @@
<div class="comment-content pl-2">
<div class="comment-header">
<div v-if="comment.pinned" class="comment-pinned">
<font-awesome-icon icon="thumbtack" />
<i class="i-fa6-solid:thumbtack" />
<span
v-t="{
path: 'comment.pinned_by',
@ -17,14 +17,20 @@
/>
</div>
<div class="comment-author flex align-center">
<div class="comment-author align-center flex">
<router-link class="link font-bold" :to="comment.commentorUrl">{{ comment.author }}</router-link>
<font-awesome-icon v-if="comment.verified" class="ml-1.5" icon="check" />
<div class="comment-meta mb-1.5" v-text="' • ' + comment.commentedTime + ' •'" />
<i v-if="comment.verified" class="i-fa6-solid:check ml-1.5" />
<div class="comment-meta mb-1.5" v-text="' · ' + comment.commentedTime + ' ·'" />
<div class="comment-footer mt-1 flex items-center">
<div class="i-fa6-solid:thumbs-up" />
<span class="ml-1" v-text="numberFormat(comment.likeCount)" />
<font-awesome-icon v-if="comment.hearted" class="ml-1" icon="heart" />
<i v-if="comment.hearted" class="i-fa6-solid:heart ml-1" />
<img
v-if="comment.creatorReplied"
:src="uploaderAvatarUrl"
class="h-5 w-5 rounded-full"
:title="$t('actions.creator_replied')"
/>
</div>
</div>
</div>
@ -33,22 +39,23 @@
<template v-if="comment.repliesPage && (!loadingReplies || !showingReplies)">
<div class="cursor-pointer" @click="loadReplies">
<a v-text="`${$t('actions.reply_count', comment.replyCount)}`" />
<font-awesome-icon class="ml-1.5" icon="level-down-alt" />
<i class="i-fa6-solid:level-down-alt ml-1.5" />
</div>
</template>
<template v-if="showingReplies">
<div class="cursor-pointer" @click="hideReplies">
<a v-t="'actions.hide_replies'" />
<font-awesome-icon class="ml-1.5" icon="level-up-alt" />
<i class="i-fa6-solid:level-up-alt ml-1.5" />
</div>
</template>
<div v-show="showingReplies" v-if="replies" class="replies">
<div v-for="reply in replies" :key="reply.commentId" class="w-full">
<!-- eslint-disable-next-line vue/no-undef-components -->
<CommentItem :comment="reply" :uploader="uploader" :video-id="videoId" />
</div>
<div v-if="nextpage" class="cursor-pointer" @click="loadReplies">
<a v-t="'actions.load_more_replies'" />
<font-awesome-icon class="ml-1.5" icon="level-down-alt" />
<i class="i-fa6-solid:level-down-alt ml-1.5" />
</div>
</div>
</div>
@ -68,6 +75,7 @@ export default {
},
},
uploader: { type: String, default: null },
uploaderAvatarUrl: { type: String, default: null },
videoId: { type: String, default: null },
},
data() {
@ -80,6 +88,7 @@ export default {
},
methods: {
async loadReplies() {
console.log(this.uploaderAvatarUrl);
if (!this.showingReplies && this.loadingReplies) {
this.showingReplies = true;
return;

View file

@ -25,5 +25,19 @@ export default {
},
},
emits: ["close", "confirm"],
mounted() {
window.addEventListener("keydown", this.handleKeyDown);
},
unmounted() {
window.removeEventListener("keydown", this.handleKeyDown);
},
methods: {
handleKeyDown(event) {
if (event.code === "Enter") {
this.$emit("confirm");
event.preventDefault();
}
},
},
};
</script>

View file

@ -0,0 +1,35 @@
<template>
<ModalComponent @close="$emit('close')">
<h2 v-t="'actions.create_group'" />
<div class="flex flex-col">
<input v-model="groupName" class="input my-4" type="text" :placeholder="$t('actions.group_name')" />
<button v-t="'actions.create_group'" class="btn ml-auto w-max" @click="createGroup()" />
</div>
</ModalComponent>
</template>
<script>
import ModalComponent from "./ModalComponent.vue";
export default {
components: { ModalComponent },
props: {
onCreateGroup: {
required: true,
type: Function,
},
},
emits: ["close"],
data() {
return {
groupName: "",
};
},
methods: {
createGroup() {
this.onCreateGroup(this.groupName);
this.$emit("close");
},
},
};
</script>

View file

@ -0,0 +1,54 @@
<template>
<ModalComponent @close="$emit('close')">
<div class="flex flex-col">
<h2 v-t="'actions.create_playlist'" />
<input ref="input" v-model="playlistName" type="text" class="input mt-2" />
<div class="ml-auto mt-3 w-min flex">
<button v-t="'actions.cancel'" class="btn" @click="$emit('close')" />
<button v-t="'actions.okay'" class="btn ml-2" @click="onCreatePlaylist" />
</div>
</div>
</ModalComponent>
</template>
<script>
import ModalComponent from "./ModalComponent.vue";
export default {
components: {
ModalComponent,
},
emits: ["created", "close"],
data() {
return {
playlistName: "",
};
},
mounted() {
this.$refs.input.focus();
window.addEventListener("keydown", this.handleKeyDown);
},
unmounted() {
window.removeEventListener("keydown", this.handleKeyDown);
},
methods: {
handleKeyDown(event) {
if (event.code === "Enter") {
this.onCreatePlaylist();
event.preventDefault();
}
},
onCreatePlaylist() {
if (!this.playlistName) return;
this.createPlaylist(this.playlistName).then(response => {
if (response.error) alert(response.error);
else {
this.$emit("created", response.playlistId, this.playlistName);
this.$emit("close");
}
});
},
},
};
</script>

View file

@ -0,0 +1,83 @@
<template>
<ModalComponent @close="$emit('close')">
<h3 v-t="'titles.custom_instances'" class="my-4 font-bold" />
<hr />
<div class="text-center">
<div>
<div v-for="(customInstance, index) in customInstances" :key="customInstance.name">
<div class="flex items-center justify-between">
<span>{{ customInstance.name }} - {{ customInstance.api_url }}</span>
<button class="pp-square" style="padding: 0" @click="removeInstance(customInstance, index)">
<i class="i-fa6-solid:circle-minus m-0" />
</button>
</div>
<hr />
</div>
</div>
<form class="flex flex-col items-end gap-2">
<input
v-model="name"
type="text"
:placeholder="$t('preferences.instance_name')"
style="max-width: unset"
/>
<input
v-model="url"
type="text"
:placeholder="$t('preferences.api_url')"
style="max-width: unset; margin: var(--efy_gap) 0"
@keyup.enter="addInstance"
/>
<button v-t="'actions.add'" @click.prevent="addInstance" />
</form>
</div>
</ModalComponent>
</template>
<script>
import ModalComponent from "./ModalComponent.vue";
export default {
components: { ModalComponent },
emits: ["close"],
data() {
return {
customInstances: [],
name: "",
url: "",
};
},
mounted() {
this.customInstances = this.getCustomInstances();
},
methods: {
async addInstance() {
const newInstance = {
name: this.name,
api_url: this.url,
};
if (!newInstance.name || !newInstance.api_url) {
return;
}
if (!this.isValidInstanceUrl(newInstance.api_url)) {
alert(this.$t("actions.invalid_url"));
return;
}
this.addCustomInstance(newInstance);
this.name = "";
this.url = "";
},
removeInstance(instance, index) {
this.customInstances.splice(index, 1);
this.removeCustomInstance(instance);
},
isValidInstanceUrl(str) {
var a = document.createElement("a");
a.href = str;
return a.host && a.host != window.location.host;
},
},
};
</script>

View file

@ -1,14 +1,14 @@
<template>
<hr />
<div class="flex flex-wrap align-center" style="place-content: space-between; gap: var(--efy_gap0)">
<div class="align-center flex flex-wrap" style="place-content: space-between; gap: var(--efy_gap0)">
<span class="buttons flex" style="gap: var(--efy_gap0)">
<router-link role="button" to="/subscriptions">Subscriptions</router-link>
<a :href="getRssUrl" role="button" class="pp-square">
<font-awesome-icon icon="rss" />
<a :href="getRssUrl" role="button" class="pp-square" style="padding: 0">
<i class="i-fa6-solid:rss m-0" />
</a>
</span>
<div class="filters flex align-center">
<div class="align-center filters flex">
<span class="flex">
<label for="filters" v-text="`${$t('actions.filter')}:`" />
<select
@ -48,29 +48,6 @@
</LoadingIndicatorPage>
</template>
<style>
.filters {
flex-wrap: wrap;
}
.filters,
.filters span {
gap: var(--efy_gap0);
}
.filters :is(select, label),
.buttons a[role="button"] {
margin: 0 !important;
white-space: nowrap;
align-items: center;
place-content: center;
}
.filters span {
align-items: center;
}
.buttons a[role="button"] {
height: var(--efy_ratio_width);
}
</style>
<script>
import VideoItem from "./VideoItem.vue";
import SortingSelector from "./SortingSelector.vue";
@ -101,14 +78,24 @@ export default {
},
filteredVideos(_this) {
const selectedGroup = _this.channelGroups.filter(group => group.groupName == _this.selectedGroupName);
const videos = this.getPreferenceBoolean("hideWatched", false)
? this.videos.filter(video => !video.watched)
: this.videos;
return _this.selectedGroupName == ""
? _this.videos
: _this.videos.filter(video => selectedGroup[0].channels.includes(video.uploaderUrl.substr(-11)));
? videos
: videos.filter(video => selectedGroup[0].channels.includes(video.uploaderUrl.substr(-24)));
},
},
mounted() {
this.fetchFeed().then(videos => {
this.videosStore = videos;
this.fetchFeed().then(resp => {
if (resp.error) {
alert(resp.error);
return;
}
this.videosStore = resp;
this.loadMoreVideos();
this.updateWatched(this.videos);
});
@ -117,18 +104,7 @@ export default {
if (!window.db) return;
const cursor = this.getChannelGroupsCursor();
cursor.onsuccess = e => {
const cursor = e.target.result;
if (cursor) {
const group = cursor.value;
this.channelGroups.push({
groupName: group.groupName,
channels: JSON.parse(group.channels),
});
cursor.continue();
}
};
this.loadChannelGroups();
},
activated() {
document.title = this.$t("titles.feed") + " - Piped";
@ -142,16 +118,9 @@ export default {
window.removeEventListener("scroll", this.handleScroll);
},
methods: {
async fetchFeed() {
if (this.authenticated) {
return await this.fetchJson(this.authApiUrl() + "/feed", {
authToken: this.getAuthToken(),
});
} else {
return await this.fetchJson(this.authApiUrl() + "/feed/unauthenticated", {
channels: this.getUnauthenticatedChannels(),
});
}
async loadChannelGroups() {
const groups = await this.getChannelGroups();
this.channelGroups.push(...groups);
},
loadMoreVideos() {
if (!this.videosStore) return;
@ -182,3 +151,26 @@ export default {
},
};
</script>
<style>
.filters {
flex-wrap: wrap;
}
.filters,
.filters span {
gap: var(--efy_gap0);
}
.filters :is(select, label),
.buttons a[role="button"] {
margin: 0 !important;
white-space: nowrap;
align-items: center;
place-content: center;
}
.filters span {
align-items: center;
}
.buttons a[role="button"] {
height: var(--efy_ratio_width);
}
</style>

View file

@ -1,28 +1,28 @@
<template>
<footer class="efy_trans_filter efy_shadow_trans efy_shadow_button_off">
<a aria-label="GitHub" href="https://github.com/TeamPiped/Piped" target="_blank">
<font-awesome-icon :icon="['fab', 'github']" />
<i class="i-fa6-brands:github" />
<span v-t="'actions.source_code'" />
</a>
<a href="https://docs.piped.video/" target="_blank">
<font-awesome-icon :icon="['fa', 'book']" />
<i class="i-fa6-solid:book" />
<span v-t="'actions.documentation'" />
</a>
<a href="https://github.com/TeamPiped/Piped#donations" target="_blank">
<font-awesome-icon :icon="['fab', 'bitcoin']" />
<i class="i-fa6-brands:bitcoin" />
<span v-t="'actions.donations'" />
</a>
<a v-if="statusPageHref" :href="statusPageHref">
<font-awesome-icon :icon="['fa', 'server']" />
<i class="i-fa6-solid:server" />
<span v-t="'actions.status_page'" />
</a>
<a v-if="donationHref" :href="donationHref">
<font-awesome-icon :icon="['fa', 'donate']" />
<i class="i-fa6-solid:money-check" />
<span v-t="'actions.instance_donations'" />
</a>
<a v-if="privacyPolicyHref" :href="privacyPolicyHref" target="_blank">
<font-awesome-icon :icon="['fa', 'eye']" />
<span v-t="'actions.instance_privacy_policy'" class="ml-2" />
<i class="i-fa6-solid:eye" />
<span v-t="'actions.instance_privacy_policy'" />
</a>
</footer>
</template>

View file

@ -1,6 +1,6 @@
<template>
<hr />
<div class="flex flex-wrap items-center place-content-between" style="gap: var(--efy_gap0)">
<div class="flex flex-wrap place-content-between items-center" style="gap: var(--efy_gap0)">
<div class="flex" style="gap: var(--efy_gap0)">
<button v-t="'actions.clear_history'" class="m-0" @click="clearHistory" />
<button v-t="'actions.export_to_json'" class="m-0" @click="exportHistory" />
@ -28,7 +28,7 @@
<option v-t="{ path: 'info.months', args: { amount: '2' } }" value="1344" />
</select>
</div>
<SortingSelector by-key="watchedAt" @apply="order => videos.sort(order)" style="gap: 0" />
<SortingSelector by-key="watchedAt" style="gap: 0" @apply="order => videos.sort(order)" />
</div>
</div>

View file

@ -9,10 +9,10 @@
<strong v-text="`Selected Subscriptions: ${selectedSubscriptions}`" />
</div>
<div efy_select>
<input v-model="override" id="import-override" type="checkbox" />
<input id="import-override" v-model="override" type="checkbox" />
<label for="import-override">Override</label>
</div>
<a class="btn w-auto" @click="handleImport" role="button" style="margin: 0">Import</a>
<a class="btn w-auto" role="button" style="margin: 0" @click="handleImport">Import</a>
</form>
<br />
<strong>Importing Subscriptions from YouTube</strong>
@ -88,10 +88,11 @@ export default {
});
}
// NewPipe
else if (text.indexOf("app_version") != -1) {
else if (text.indexOf("subscriptions") != -1) {
const json = JSON.parse(text);
json.subscriptions
.filter(item => item.service_id == 0)
// if service_id is undefined, chances are it's a freetube export
.filter(item => item.service_id == 0 || item.service_id == undefined)
.forEach(item => {
const url = item.url;
const id = url.slice(-24);

View file

@ -1,6 +1,6 @@
<template>
<ModalComponent>
<h5 v-t="'titles.account'" class="font-bold my-4" />
<h5 v-t="'titles.account'" class="my-4 font-bold" />
<hr />
<div class="text-center">
<form class="children:pb-3">
@ -12,7 +12,7 @@
autocomplete="username"
:placeholder="$t('login.username')"
:aria-label="$t('login.username')"
v-on:keyup.enter="login"
@keyup.enter="login"
/>
</div>
<div>
@ -23,12 +23,12 @@
autocomplete="password"
:placeholder="$t('login.password')"
:aria-label="$t('login.password')"
v-on:keyup.enter="login"
@keyup.enter="login"
/>
</div>
<div class="flex justify-end p-0!" style="gap: var(--efy_gap0)">
<a role="button" class="m-0!" @click="register" v-t="'titles.register'" />
<a role="button" class="m-0!" @click="login" v-t="'titles.login'" />
<a v-t="'titles.register'" role="button" class="m-0!" @click="register" />
<a v-t="'titles.login'" role="button" class="m-0!" @click="login" />
</div>
</form>
</div>
@ -38,6 +38,7 @@
<script>
import ModalComponent from "./ModalComponent.vue";
export default {
components: { ModalComponent },
data() {
return {
username: null,
@ -85,6 +86,5 @@ export default {
});
},
},
components: { ModalComponent },
};
</script>

View file

@ -1,8 +1,11 @@
<template>
<h1 v-t="'titles.login'" class="my-4 text-center font-bold" />
<div class="flex justify-center">
<h1 v-t="'titles.login'" class="my-4 text-center font-bold" />
<i class="i-fa6-solid:circle-info ml-2 mt-6 cursor-pointer" :title="$t('info.login_note')" />
</div>
<hr />
<div class="text-center">
<form class="children:pb-3">
<div class="w-full flex items-center justify-center text-center">
<form class="w-min children:pb-3">
<div>
<input
v-model="username"
@ -43,7 +46,7 @@ export default {
mounted() {
//TODO: Add Server Side check
if (this.getAuthToken()) {
this.$router.push("/");
this.$router.push(import.meta.env.BASE_URL);
}
},
activated() {
@ -61,7 +64,7 @@ export default {
}).then(resp => {
if (resp.token) {
this.setPreference("authToken" + this.hashCode(this.authApiUrl()), resp.token);
window.location = "/"; // done to bypass cache
window.location = import.meta.env.BASE_URL; // done to bypass cache
} else alert(resp.error);
});
},

View file

@ -2,8 +2,8 @@
<div class="modal">
<div @click="handleClick">
<div class="modal-container">
<button @click="$emit('close')" class="pp-color btn m-0">
<font-awesome-icon icon="xmark" />
<button class="pp-square btn pp-color m-0" style="padding: 0" @click="$emit('close')">
<i class="i-fa6-solid:xmark m-0" />
</button>
<slot></slot>
</div>

View file

@ -1,7 +1,7 @@
<template>
<nav class="pp-nav flex flex-wrap items-center justify-center px-2 sm:px-4 py-2.5 w-full relative">
<div class="flex-1 flex justify-start pp-logo">
<router-link class="flex font-bold text-3xl items-center font-sans" to="/">
<nav class="pp-nav relative w-full flex flex-wrap items-center justify-center px-2 py-2.5 sm:px-4">
<div class="pp-logo flex flex-1 justify-start">
<router-link class="flex items-center text-3xl font-bold font-sans" to="/">
<svg
id="svg-logo"
version="1.2"
@ -54,7 +54,7 @@
>iped</router-link
>
</div>
<div class="lt-md:hidden flex flex-1 justify-start" style="position: relative">
<div class="flex flex-1 justify-start lt-md:hidden" style="position: relative">
<input
ref="videoSearch"
v-model="searchText"
@ -88,7 +88,7 @@
<button
efy_sidebar_btn="relative, pp-desktop"
style="background: transparent; padding: 0; margin: -5rem 0 0 0; border: 0"
class="efy_trans_filter_off efy_shadow_button_off"
class="efy_shadow_button_off efy_trans_filter_off"
>
<i efy_icon="menu" style="margin: 0" />
</button>
@ -96,18 +96,18 @@
</nav>
<!-- search suggestions for mobile devices -->
<div class="w-{full - 4} md:hidden" style="position: relative">
<div class="- 4} w-{full md:hidden" style="position: relative">
<input
v-model="searchText"
type="text"
role="search"
:title="$t('actions.search')"
:placeholder="$t('actions.search')"
style="margin: 15rem 0 0 0"
@keyup="onKeyUp"
@keypress="onKeyPress"
@focus="onInputFocus"
@blur="onInputBlur"
style="margin: 15rem 0 0 0"
/>
<span v-if="searchText" class="delete-search" @click="searchText = ''"></span>
</div>
@ -120,6 +120,104 @@
<LoginModal v-if="showLoginModal" @close="showLoginModal = !showLoginModal" />
</template>
<script>
import SearchSuggestions from "./SearchSuggestions.vue";
import LoginModal from "./LoginModal.vue";
import hotkeys from "hotkeys-js";
export default {
components: {
SearchSuggestions,
LoginModal,
},
data() {
return {
searchText: "",
suggestionsVisible: false,
showLoginModal: false,
showTopNav: false,
homePagePath: import.meta.env.BASE_URL,
registrationDisabled: false,
};
},
computed: {
shouldShowLogin(_this) {
return _this.getAuthToken() == null;
},
shouldShowRegister(_this) {
return _this.registrationDisabled == false ? _this.shouldShowLogin : false;
},
shouldShowHistory(_this) {
return _this.getPreferenceBoolean("watchHistory", false);
},
shouldShowTrending(_this) {
return _this.getPreferenceString("homepage", "trending") != "trending";
},
showSearchHistory(_this) {
return _this.getPreferenceBoolean("searchHistory", false) && localStorage.getItem("search_history");
},
},
mounted() {
this.fetchAuthConfig();
const query = new URLSearchParams(window.location.search).get("search_query");
if (query) this.onSearchTextChange(query);
this.focusOnSearchBar();
this.homePagePath = this.getHomePage(this);
},
methods: {
// focus on search bar when Ctrl+k is pressed
focusOnSearchBar() {
hotkeys("ctrl+k", event => {
event.preventDefault();
this.$refs.videoSearch.focus();
});
},
onKeyUp(e) {
if (e.key === "ArrowUp" || e.key === "ArrowDown") {
e.preventDefault();
}
this.$refs.searchSuggestions.onKeyUp(e);
},
onKeyPress(e) {
if (e.key === "Enter") {
this.submitSearch(e);
}
},
onInputFocus() {
if (this.showSearchHistory) this.$refs.searchSuggestions.refreshSuggestions();
this.suggestionsVisible = true;
},
onInputBlur() {
// the search suggestions will be hidden after some seconds
// otherwise anchor links won't work!
setTimeout(() => (this.suggestionsVisible = false), 200);
},
onSearchTextChange(searchText) {
this.searchText = searchText;
},
async fetchAuthConfig() {
this.fetchJson(this.authApiUrl() + "/config").then(config => {
this.registrationDisabled = config?.registrationDisabled === true;
});
},
onSearchClick(e) {
this.submitSearch(e);
},
submitSearch(e) {
e.target.blur();
if (this.searchText) {
this.$router.push({
name: "SearchResults",
query: { search_query: this.searchText },
});
} else {
this.$router.push("/");
}
return;
},
},
};
</script>
<style>
.pp-nav {
gap: 15rem;
@ -182,95 +280,3 @@
align-content: center;
}
</style>
<script>
import SearchSuggestions from "./SearchSuggestions.vue";
import LoginModal from "./LoginModal.vue";
import hotkeys from "hotkeys-js";
export default {
components: {
SearchSuggestions,
LoginModal,
},
data() {
return {
searchText: "",
suggestionsVisible: false,
showLoginModal: false,
showTopNav: false,
homePagePath: "/",
registrationDisabled: false,
};
},
computed: {
shouldShowLogin(_this) {
return _this.getAuthToken() == null;
},
shouldShowRegister(_this) {
return _this.registrationDisabled == false ? _this.shouldShowLogin : false;
},
shouldShowHistory(_this) {
return _this.getPreferenceBoolean("watchHistory", false);
},
shouldShowTrending(_this) {
return _this.getPreferenceString("homepage", "trending") != "trending";
},
showSearchHistory(_this) {
return _this.getPreferenceBoolean("searchHistory", false) && localStorage.getItem("search_history");
},
},
mounted() {
this.fetchAuthConfig();
const query = new URLSearchParams(window.location.search).get("search_query");
if (query) this.onSearchTextChange(query);
this.focusOnSearchBar();
this.homePagePath = this.getHomePage(this);
},
methods: {
// focus on search bar when Ctrl+k is pressed
focusOnSearchBar() {
hotkeys("ctrl+k", event => {
event.preventDefault();
this.$refs.videoSearch.focus();
});
},
onKeyUp(e) {
if (e.key === "ArrowUp" || e.key === "ArrowDown") {
e.preventDefault();
}
this.$refs.searchSuggestions.onKeyUp(e);
},
onKeyPress(e) {
if (e.key === "Enter") {
this.submitSearch(e);
}
},
onInputFocus() {
if (this.showSearchHistory) this.$refs.searchSuggestions.refreshSuggestions();
this.suggestionsVisible = true;
},
onInputBlur() {
this.suggestionsVisible = false;
},
onSearchTextChange(searchText) {
this.searchText = searchText;
},
async fetchAuthConfig() {
this.fetchJson(this.authApiUrl() + "/config").then(config => {
this.registrationDisabled = config?.registrationDisabled === true;
});
},
onSearchClick(e) {
this.submitSearch(e);
},
submitSearch(e) {
e.target.blur();
this.$router.push({
name: "SearchResults",
query: { search_query: this.searchText },
});
return;
},
},
};
</script>

View file

@ -1,6 +1,6 @@
<template>
<div class="flex flex-col justify-center items-center min-h-[88vh]">
<h1 class="font-bold !text-[170rem] mb-[-6vh]">404</h1>
<div class="min-h-[88vh] flex flex-col items-center justify-center">
<h1 class="mb-[-6vh] font-bold !text-[170rem]">404</h1>
<h2 v-t="'info.page_not_found'" class="!text-[40rem]" />
<a v-t="'actions.back_to_home'" role="button" href="/" />
</div>

View file

@ -1,11 +1,16 @@
<template>
<ModalComponent @close="$emit('close')">
<h4 v-t="'actions.select_playlist'" class="mb-2" />
<select v-model="selectedPlaylist" class="select w-full mb-2">
<select v-model="selectedPlaylist" class="select mb-2 w-full">
<option v-for="playlist in playlists" :key="playlist.id" :value="playlist.id" v-text="playlist.name" />
</select>
<div class="flex justify-end" style="gap: var(--efy_gap0)">
<button ref="addButton" v-t="'actions.create_playlist'" class="btn pp-color" @click="onCreatePlaylist" />
<button
ref="addButton"
v-t="'actions.create_playlist'"
class="btn pp-color"
@click="showCreatePlaylistModal = true"
/>
<button
ref="addButton"
v-t="'actions.add_to_playlist'"
@ -14,14 +19,21 @@
/>
</div>
</ModalComponent>
<CreatePlaylistModal
v-if="showCreatePlaylistModal"
@close="showCreatePlaylistModal = false"
@created="addCreatedPlaylist"
/>
</template>
<script>
import ModalComponent from "./ModalComponent.vue";
import CreatePlaylistModal from "./CreatePlaylistModal.vue";
export default {
components: {
ModalComponent,
CreatePlaylistModal,
},
props: {
videoInfo: {
@ -39,10 +51,13 @@ export default {
playlists: [],
selectedPlaylist: null,
processing: false,
showCreatePlaylistModal: false,
};
},
mounted() {
this.fetchPlaylists();
this.getPlaylists().then(json => {
this.playlists = json;
});
this.selectedPlaylist = this.getPreferenceString("selectedPlaylist" + this.hashCode(this.authApiUrl()));
window.addEventListener("keydown", this.handleKeyDown);
window.blur();
@ -52,7 +67,7 @@ export default {
},
methods: {
handleKeyDown(event) {
if (event.code === "Enter") {
if (event.code === "Enter" && !this.showCreatePlaylistModal) {
this.handleClick(this.selectedPlaylist);
event.preventDefault();
}
@ -74,18 +89,9 @@ export default {
if (json.error) alert(json.error);
});
},
async fetchPlaylists() {
this.getPlaylists().then(json => {
this.playlists = json;
});
},
onCreatePlaylist() {
const name = prompt(this.$t("actions.create_playlist"));
if (!name) return;
this.createPlaylist(name).then(json => {
if (json.error) alert(json.error);
else this.fetchPlaylists();
});
addCreatedPlaylist(playlistId, playlistName) {
this.playlists.push({ id: playlistId, name: playlistName });
this.selectedPlaylist = playlistId;
},
},
};

View file

@ -1,11 +1,11 @@
<template>
<div class="video-card flex flex-col flex-justify-between efy_shadow_trans">
<div class="efy_shadow_trans video-card flex flex-col flex-justify-between">
<router-link :to="props.item.url">
<div class="relative">
<img class="thumbnail" :src="props.item.thumbnail" loading="lazy" />
</div>
<div class="flex items-center h-[44rem] overflow-hidden">
<p v-text="props.item.name" class="pp-video-card-title" />
<div class="h-[44rem] flex items-center overflow-hidden">
<p class="pp-video-card-title" v-text="props.item.name" />
</div>
</router-link>
<p v-if="props.item.description" v-text="props.item.description" />
@ -13,8 +13,8 @@
<div class="pp-video-card-buttons">
<button
v-if="props.item.videos >= 0"
v-text="`${props.item.videos} ${$t('video.videos')}`"
class="efy_shadow_trans efy_shadow_button_off efy_button_text_off"
v-text="`${props.item.videos} ${$t('video.videos')}`"
/>
<router-link
v-if="props.item.uploaderUrl && item.uploaderName"
@ -24,8 +24,8 @@
style="padding: 0; flex-grow: 1; background: transparent; border: 0"
>
<div class="pp-text efy_shadow_trans efy_shadow_button_off flex-grow-1">
<span v-text="props.item.uploaderName" style="max-width: 106rem" />
<font-awesome-icon class="ml-1.5" v-if="item.uploaderVerified" icon="check" />
<span style="max-width: 106rem" v-text="props.item.uploaderName" />
<i v-if="item.uploaderVerified" class="i-fa6-solid:check ml-2" />
</div>
</router-link>
<a

View file

@ -21,31 +21,31 @@
loading="lazy"
width="36"
height="36"
class="w-36rem h-36rem efy_shadow_trans"
class="efy_shadow_trans h-36rem w-36rem"
/>
<button class="pp-text efy_shadow_trans efy_shadow_button_off efy_button_text_off">
<span v-text="playlist.uploader" />
<font-awesome-icon class="ml-1.5" v-if="playlist.uploaderVerified" icon="check" />
<i v-if="playlist.uploaderVerified" class="i-fa6-solid:check ml-1.5" />
</button>
</router-link>
<button
v-text="`${playlist.videos} ${$t('video.videos')}`"
class="efy_button_text_off efy_shadow_trans efy_shadow_button_off"
v-text="`${playlist.videos} ${$t('video.videos')}`"
/>
</div>
<div class="pp-flex-bookmarks">
<button v-if="!isPipedPlaylist" class="btn" @click="bookmarkPlaylist">
<font-awesome-icon class="mr-[5rem]" icon="bookmark" />
<i class="i-fa6-solid:bookmark mr-[5rem]" />
{{ $t(`actions.${isBookmarked ? "playlist_bookmarked" : "bookmark_playlist"}`) }}
</button>
<button v-if="authenticated && !isPipedPlaylist" class="btn mr-1 ml-2" @click="clonePlaylist">
<font-awesome-icon class="mr-[5rem]" icon="clone" />{{ $t("actions.clone_playlist") }}
<button v-if="authenticated && !isPipedPlaylist" class="btn ml-2 mr-1" @click="clonePlaylist">
<i class="i-fa6-solid:clone mr-[5rem]" />{{ $t("actions.clone_playlist") }}
</button>
<button class="btn mr-1" @click="downloadPlaylistAsTxt">
{{ $t("actions.download_as_txt") }}
</button>
<a :href="getRssUrl" role="button" class="btn pp-square">
<font-awesome-icon icon="rss" />
<a :href="getRssUrl" role="button" class="btn pp-square" style="padding: 0">
<i class="i-fa6-solid:rss m-0" />
</a>
<WatchOnButton :link="`https://www.youtube.com/playlist?list=${$route.query.list}`" class="pp-square" />
</div>
@ -69,17 +69,6 @@
</LoadingIndicatorPage>
</template>
<style>
.pp-flex-bookmarks {
display: flex;
flex-wrap: wrap;
gap: var(--efy_gap0);
}
.pp-flex-bookmarks > * {
margin: 0;
}
</style>
<script>
import ErrorHandler from "./ErrorHandler.vue";
import LoadingIndicatorPage from "./LoadingIndicatorPage.vue";
@ -132,16 +121,8 @@ export default {
window.removeEventListener("scroll", this.handleScroll);
},
methods: {
async fetchPlaylist() {
const playlistId = this.$route.query.list;
if (playlistId.startsWith("local")) {
return this.getPlaylist(playlistId);
}
return await await this.fetchJson(this.authApiUrl() + "/playlists/" + this.$route.query.list);
},
async getPlaylistData() {
this.fetchPlaylist()
this.getPlaylist(this.$route.query.list)
.then(data => (this.playlist = data))
.then(() => {
this.updateTitle();
@ -237,3 +218,14 @@ export default {
},
};
</script>
<style>
.pp-flex-bookmarks {
display: flex;
flex-wrap: wrap;
gap: var(--efy_gap0);
}
.pp-flex-bookmarks > * {
margin: 0;
}
</style>

View file

@ -1,12 +1,13 @@
<template>
<h6 efy_card style="padding: 5rem 10rem 3rem; margin: 0 0 15rem 0">Playlist</h6>
<div class="overflow-y-scroll h-screen-sm pp-show-playlist" ref="scrollable">
<div ref="scrollable" class="pp-show-playlist h-screen-sm overflow-y-scroll">
<VideoItem
v-for="(related, index) in playlist.relatedStreams"
:key="related.url"
:item="related"
:index="index"
:playlist-id="playlistId"
:prefer-listen="preferListen"
height="94"
width="168"
/>
@ -16,6 +17,7 @@
<script>
import { nextTick } from "vue";
import VideoItem from "./VideoItem.vue";
export default {
components: { VideoItem },
props: {
@ -31,6 +33,10 @@ export default {
type: Number,
required: true,
},
preferListen: {
type: Boolean,
default: false,
},
},
watch: {
playlist: {

View file

@ -1,27 +1,27 @@
<template>
<hr />
<div class="flex flex-wrap justify-between items-center" style="gap: var(--efy_gap0)">
<div class="flex flex-wrap items-center justify-between" style="gap: var(--efy_gap0)">
<button
v-t="'actions.create_playlist'"
style="height: var(--efy_ratio_width); margin: 0"
@click="onCreatePlaylist"
@click="showCreatePlaylistModal = true"
/>
<div class="flex flex-wrap" style="gap: var(--efy_gap0)">
<button
v-if="playlists.length > 0"
v-t="'actions.export_to_json'"
@click="exportPlaylists"
style="height: var(--efy_ratio_width); margin: 0"
@click="exportPlaylists"
/>
<input
id="fileSelector"
ref="fileSelector"
type="file"
class="display-none"
class="hidden"
multiple="multiple"
@change="importPlaylists"
/>
<label v-t="'actions.import_from_json_csv'" for="fileSelector" class="m-0! font-bold" role="button" />
<label v-t="'actions.import_from_json_csv'" for="fileSelector" class="font-bold m-0!" role="button" />
</div>
</div>
<hr />
@ -32,15 +32,15 @@
<img class="thumbnail" :src="playlist.thumbnail" alt="thumbnail" />
<p
style="display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; margin: 0 15rem"
class="flex link"
class="link flex"
:title="playlist.name"
v-text="playlist.name"
/>
</router-link>
<div class="pp-video-card-buttons flex gap-15rem children:m-0" style="flex-wrap: wrap">
<button
v-text="`${playlist.videos} ${$t('video.videos')}`"
class="efy_shadow_trans efy_shadow_button_off efy_button_text_off"
v-text="`${playlist.videos} ${$t('video.videos')}`"
/>
<button
v-t="'actions.edit_playlist'"
@ -86,39 +86,46 @@
<div
v-for="(playlist, index) in bookmarks"
:key="playlist.playlistId"
class="pp-bookmark video-card efy_trans_filter efy_shadow_trans"
class="video-card efy_trans_filter efy_shadow_trans pp-bookmark"
>
<router-link :to="`/playlist?list=${playlist.playlistId}`">
<img class="thumbnail" :src="playlist.thumbnail" alt="thumbnail" />
<div class="flex items-center h-[44rem] overflow-hidden">
<div class="h-[44rem] flex items-center overflow-hidden">
<p class="pp-video-card-title" :title="playlist.name" v-text="playlist.name" />
</div>
</router-link>
<div class="pp-video-card-buttons flex gap-15rem">
<button @click.prevent="removeBookmark(index)" class="btn pp-color aspect-square">
<font-awesome-icon icon="bookmark" />
<button class="btn pp-color aspect-square" @click.prevent="removeBookmark(index)">
<i class="i-fa6-solid:bookmark m-0" />
</button>
<button
v-text="`${playlist.videos} ${$t('video.videos')}`"
class="efy_shadow_trans efy_shadow_button_off efy_button_text_off"
v-text="`${playlist.videos} ${$t('video.videos')}`"
/>
</div>
<a :href="playlist.uploaderUrl" class="pp-video-card-channel">
<img class="w-36rem h-36rem efy_shadow_trans" :src="playlist.uploaderAvatar" width="36" height="36" />
<img class="efy_shadow_trans h-36rem w-36rem" :src="playlist.uploaderAvatar" width="36" height="36" />
<div class="pp-text efy_shadow_trans">
<span v-text="playlist.uploader" />
</div>
</a>
</div>
</div>
<br />
<CreatePlaylistModal
v-if="showCreatePlaylistModal"
@close="showCreatePlaylistModal = false"
@created="fetchPlaylists"
/>
</template>
<script>
import ConfirmModal from "./ConfirmModal.vue";
import ModalComponent from "./ModalComponent.vue";
import CreatePlaylistModal from "./CreatePlaylistModal.vue";
export default {
components: { ConfirmModal, ModalComponent },
components: { ConfirmModal, ModalComponent, CreatePlaylistModal },
data() {
return {
playlists: [],
@ -127,6 +134,7 @@ export default {
playlistToEdit: null,
newPlaylistName: "",
newPlaylistDescription: "",
showCreatePlaylistModal: false,
};
},
mounted() {
@ -172,14 +180,6 @@ export default {
});
this.playlistToDelete = null;
},
onCreatePlaylist() {
const name = prompt(this.$t("actions.create_playlist"));
if (!name) return;
this.createPlaylist(name).then(json => {
if (json.error) alert(json.error);
else this.fetchPlaylists();
});
},
async exportPlaylists() {
if (!this.playlists) return;
let json = {

View file

@ -85,8 +85,19 @@
</select>
</label>
</template>
<div class="pref">
<span v-t="'titles.custom_instances'" class="w-max" />
<button v-t="'actions.customize'" class="btn" @click="showCustomInstancesModal = true" />
<CustomInstanceModal
v-if="showCustomInstancesModal"
@close="
showCustomInstancesModal = false;
fetchInstances();
"
/>
</div>
<div class="pref items-start! flex-col">
<div class="pref flex-col items-start!">
<strong>Preferences</strong>
<div class="flex flex-wrap" style="gap: var(--efy_gap0)">
<button style="height: var(--efy_ratio_width)" @click="showConfirmResetPrefsDialog = true">
@ -113,7 +124,7 @@
/>
</div>
<!-- options that are visible only when logged in -->
<div v-if="authenticated" class="pref items-start! flex-col">
<div v-if="authenticated" class="pref flex-col items-start!">
<label v-t="'actions.delete_account'" for="txtDeleteAccountPassword" class="font-bold" />
<div class="flex flex-wrap" style="gap: var(--efy_gap0)">
<input
@ -129,13 +140,14 @@
<button v-t="'actions.delete_account'" class="w-auto" @click="deleteAccount" />
</div>
</div>
<div v-if="authenticated" class="pref items-start! flex-col" style="border-bottom: var(--efy_border)">
<div v-if="authenticated" class="pref flex-col items-start!" style="border-bottom: var(--efy_border)">
<strong>Logout</strong>
<div class="flex flex-wrap" style="gap: var(--efy_gap0)">
<button v-t="'actions.logout'" class="w-auto" @click="logout" />
<button v-t="'actions.invalidate_session'" class="w-auto" @click="invalidateSession" />
</div>
</div>
<hr />
</div>
<div efy_card="grid">
<h5 v-t="'titles.player'" />
@ -338,6 +350,16 @@
@change="onChange($event)"
/>
</label>
<label class="pref" for="txtPrefetchLimit">
<strong v-t="'actions.concurrent_prefetch_limit'" />
<input
id="txtPrefetchLimit"
v-model="prefetchLimit"
class="input w-24"
type="text"
@change="onChange($event)"
/>
</label>
</div>
<div efy_card="grid">
@ -409,10 +431,11 @@
<th v-t="'preferences.registered_users'" />
<th v-t="'preferences.version'" class="lt-md:hidden" />
<th v-t="'preferences.up_to_date'" />
<th v-t="'preferences.uptime_30d'" />
<th v-t="'preferences.ssl_score'" />
</tr>
</thead>
<tbody v-for="instance in instances" :key="instance.name">
<tbody v-for="instance in publicInstances" :key="instance.name">
<tr>
<td v-text="instance.name" />
<td v-text="instance.locations" />
@ -420,6 +443,7 @@
<td v-text="instance.registered" />
<td class="lt-md:hidden" v-text="instance.version" />
<td v-text="`${instance.up_to_date ? '&#9989;' : '&#10060;'}`" />
<td v-text="`${Number.parseFloat(instance.uptime_30d.toFixed(2))}%`" />
<td>
<a v-t="'actions.view_ssl_score'" :href="sslScore(instance.api_url)" target="_blank" />
</td>
@ -431,9 +455,11 @@
<script>
import CountryMap from "@/utils/CountryMaps/en.json";
import ConfirmModal from "./ConfirmModal.vue";
import CustomInstanceModal from "./CustomInstanceModal.vue";
export default {
components: {
ConfirmModal,
CustomInstanceModal,
},
data() {
return {
@ -441,7 +467,8 @@ export default {
selectedInstance: null,
authInstance: false,
selectedAuthInstance: null,
instances: [],
customInstances: [],
publicInstances: [],
sponsorBlock: true,
skipOptions: new Map([
["sponsor", { value: "auto", label: "actions.skip_sponsors" }],
@ -469,7 +496,7 @@ export default {
countrySelected: "US",
defaultHomepage: "trending",
minimizeComments: false,
minimizeDescription: false,
minimizeDescription: true,
minimizeRecommendations: false,
minimizeChapters: false,
showWatchOnYouTube: false,
@ -518,6 +545,7 @@ export default {
{ code: "ro", name: "Română" },
{ code: "ru", name: "Русский" },
{ code: "si", name: "සිංහල" },
{ code: "sl", name: "Slovenian" },
{ code: "sr", name: "Српски" },
{ code: "sv", name: "Svenska" },
{ code: "ta", name: "தமிழ்" },
@ -531,29 +559,27 @@ export default {
enabledCodecs: ["vp9", "avc"],
disableLBRY: false,
proxyLBRY: false,
prefetchLimit: 2,
password: null,
showConfirmResetPrefsDialog: false,
showCustomInstancesModal: false,
};
},
computed: {
instances() {
return [...this.publicInstances, ...this.customInstances];
},
},
activated() {
document.title = this.$t("titles.preferences") + " - Piped";
},
async mounted() {
if (Object.keys(this.$route.query).length > 0) this.$router.replace({ query: {} });
this.fetchJson("https://piped-instances.kavin.rocks/").then(resp => {
this.instances = resp;
if (!this.instances.some(instance => instance.api_url == this.apiUrl()))
this.instances.push({
name: "Custom Instance",
api_url: this.apiUrl(),
locations: "Unknown",
cdn: false,
});
});
this.fetchInstances();
if (this.testLocalStorage) {
this.selectedInstance = this.getPreferenceString("instance", "https://pipedapi.kavin.rocks");
this.selectedInstance = this.getPreferenceString("instance", import.meta.env.VITE_PIPED_API);
this.authInstance = this.getPreferenceBoolean("authInstance", false);
this.selectedAuthInstance = this.getPreferenceString("auth_instance_url", this.selectedInstance);
@ -588,7 +614,7 @@ export default {
this.countrySelected = this.getPreferenceString("region", "US");
this.defaultHomepage = this.getPreferenceString("homepage", "trending");
this.minimizeComments = this.getPreferenceBoolean("minimizeComments", false);
this.minimizeDescription = this.getPreferenceBoolean("minimizeDescription", false);
this.minimizeDescription = this.getPreferenceBoolean("minimizeDescription", true);
this.minimizeRecommendations = this.getPreferenceBoolean("minimizeRecommendations", false);
this.minimizeChapters = this.getPreferenceBoolean("minimizeChapters", false);
this.showWatchOnYouTube = this.getPreferenceBoolean("showWatchOnYouTube", false);
@ -599,6 +625,7 @@ export default {
this.enabledCodecs = this.getPreferenceString("enabledCodecs", "vp9,avc").split(",");
this.disableLBRY = this.getPreferenceBoolean("disableLBRY", false);
this.proxyLBRY = this.getPreferenceBoolean("proxyLBRY", false);
this.prefetchLimit = this.getPreferenceNumber("prefetchLimit", 2);
this.hideWatched = this.getPreferenceBoolean("hideWatched", false);
this.mobileChapterLayout = this.getPreferenceString("mobileChapterLayout", "Vertical");
if (this.selectedLanguage != "en") {
@ -661,12 +688,28 @@ export default {
localStorage.setItem("enabledCodecs", this.enabledCodecs.join(","));
localStorage.setItem("disableLBRY", this.disableLBRY);
localStorage.setItem("proxyLBRY", this.proxyLBRY);
localStorage.setItem("prefetchLimit", this.prefetchLimit);
localStorage.setItem("hideWatched", this.hideWatched);
localStorage.setItem("mobileChapterLayout", this.mobileChapterLayout);
if (shouldReload) window.location.reload();
}
},
async fetchInstances() {
this.customInstances = this.getCustomInstances();
this.fetchJson(import.meta.env.VITE_PIPED_INSTANCES).then(resp => {
this.publicInstances = resp;
if (!this.publicInstances.some(instance => instance.api_url == this.apiUrl()))
this.publicInstances.push({
name: "Selected Instance",
api_url: this.apiUrl(),
locations: "Unknown",
cdn: false,
uptime_30d: 100,
});
});
},
sslScore(url) {
return "https://www.ssllabs.com/ssltest/analyze.html?d=" + new URL(url).host + "&latest";
},
@ -689,14 +732,14 @@ export default {
// reset the auth token
localStorage.removeItem("authToken" + this.hashCode(this.authApiUrl()));
// redirect to trending page
window.location = "/";
window.location = import.meta.env.BASE_URL;
},
resetPreferences() {
this.showConfirmResetPrefsDialog = false;
// clear the local storage
localStorage.clear();
// redirect to the home page
window.location = "/";
window.location = import.meta.env.BASE_URL;
},
async invalidateSession() {
this.fetchJson(this.authApiUrl() + "/logout", null, {
@ -749,19 +792,23 @@ export default {
max-width: 250rem;
}
.pp-pref-cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300rem, 1fr));
gap: var(--efy_gap);
margin-top: 15rem;
}
[efy_card*="grid"] {
padding: 0;
gap: 0;
}
[efy_card*="grid"]:active {
transform: scale(1) !important;
scale: 1;
}
[efy_card*="grid"] h5 {
padding: 5rem 10rem;
}
tbody:nth-child(odd) {
background: var(--efy_bg1) !important;
table {
margin: 0;
tbody:nth-child(odd) {
background: var(--efy_bg1) !important;
}
}
</style>

View file

@ -1,8 +1,11 @@
<template>
<h1 v-t="'titles.register'" class="my-4 text-center font-bold" />
<div class="flex justify-center">
<h1 v-t="'titles.register'" class="my-4 text-center font-bold" />
<i class="i-fa6-solid:circle-info ml-2 mt-6 cursor-pointer" :title="$t('info.register_note')" />
</div>
<hr />
<div class="flex justify-center text-center">
<form class="items-center px-3 children:pb-3">
<div class="flex flex-col items-center justify-center text-center">
<form class="w-max items-center px-3 children:pb-3">
<div>
<input
v-model="username"
@ -17,7 +20,7 @@
<div class="flex justify-center">
<input
v-model="password"
class="input w-full"
class="input h-auto w-full"
:type="showPassword ? 'text' : 'password'"
autocomplete="password"
:placeholder="$t('login.password')"
@ -31,7 +34,7 @@
<div class="flex justify-center">
<input
v-model="passwordConfirm"
class="input w-full"
class="input h-auto w-full"
:type="showConfirmPassword ? 'text' : 'password'"
autocomplete="password"
:placeholder="$t('login.password_confirm')"
@ -79,7 +82,7 @@ export default {
mounted() {
//TODO: Add Server Side check
if (this.getAuthToken()) {
this.$router.push("/");
this.$router.push(import.meta.env.BASE_URL);
}
},
activated() {
@ -105,7 +108,7 @@ export default {
}).then(resp => {
if (resp.token) {
this.setPreference("authToken" + this.hashCode(this.authApiUrl()), resp.token);
window.location = "/"; // done to bypass cache
window.location = import.meta.env.BASE_URL; // done to bypass cache
} else alert(resp.error);
});
},

View file

@ -3,7 +3,7 @@
<div class="flex flex-wrap place-content-between items-center">
<h5 class="ml-[5rem]" v-text="$route.query.search_query" />
<div class="flex items-center" style="gap: var(--efy_gap0)">
<label v-text="`${$t('actions.filter')}:`" for="ddlSearchFilters" />
<label for="ddlSearchFilters" v-text="`${$t('actions.filter')}:`" />
<select
id="ddlSearchFilters"
v-model="selectedFilter"

View file

@ -4,12 +4,14 @@
<li
v-for="(suggestion, i) in searchSuggestions"
:key="i"
class="suggestion"
:class="{ 'suggestion-selected': selected === i }"
@mouseover="onMouseOver(i)"
@mousedown.stop="onClick(i)"
v-text="suggestion"
/>
@click="setSelected(i)"
>
<router-link class="suggestion" :to="`/results?search_query=${encodeURIComponent(suggestion)}`">
{{ suggestion }}
</router-link>
</li>
</ul>
</div>
</template>
@ -69,13 +71,6 @@ export default {
this.selected = i;
}
},
onClick(i) {
this.setSelected(i);
this.$router.push({
name: "SearchResults",
query: { search_query: this.searchSuggestions[i] },
});
},
setSelected(val) {
this.selected = val;
this.$emit("searchchange", this.searchSuggestions[this.selected]);
@ -91,5 +86,15 @@ export default {
box-shadow: 0 0 20rem var(--efy_text_trans);
padding: var(--efy_gap);
margin: calc(40rem + var(--efy_gap)) 0 var(--efy_gap) 0;
li {
border: var(--efy_border_size) solid transparent;
border-radius: var(--efy_radius0);
}
.suggestion-selected {
border: var(--efy_border);
}
a {
-webkit-text-fill-color: var(--efy_text) !important;
}
}
</style>

View file

@ -1,10 +1,11 @@
<template>
<ModalComponent>
<h5 v-t="'actions.share'" />
<div class="flex justify-between mt-2 mb-2">
<div class="mb-2 mt-2 flex justify-between">
<label v-t="'actions.piped_link'" />
<input v-model="pipedLink" type="checkbox" @change="onChange" />
</div>
<hr />
<div v-if="hasPlaylist" class="flex justify-between">
<label v-t="'actions.with_playlist'" />
<input v-model="withPlaylist" type="checkbox" @change="onChange" />
@ -13,10 +14,11 @@
<label v-t="'actions.with_timecode'" for="withTimeCode" />
<input id="withTimeCode" v-model="withTimeCode" type="checkbox" @change="onChange" />
</div>
<div v-if="withTimeCode" class="flex justify-between mt-2" style="align-items: center">
<div v-if="withTimeCode" class="mt-2 flex justify-between" style="align-items: center">
<label v-t="'actions.time_code'" />
<input v-model="timeStamp" style="max-width: 100rem" type="number" @change="onChange" />
<input v-model="timeStamp" style="max-width: 100rem; margin: 0" type="number" @change="onChange" />
</div>
<hr />
<a :href="generatedLink" target="_blank">
<h6 class="mb-2 mt-2" v-text="generatedLink" />
</a>

View file

@ -1,6 +1,6 @@
<template>
<label v-t="'actions.sort_by'" for="ddlSortBy" class="m-0" />
<select id="ddlSortBy" v-model="selectedSort" class="w-auto m-0">
<select id="ddlSortBy" v-model="selectedSort" class="m-0 w-auto">
<option v-for="(value, key) in options" :key="key" v-t="`actions.${key}`" :value="value" />
</select>
</template>

View file

@ -1,7 +1,7 @@
<template>
<hr />
<!-- import / export section -->
<div class="flex justify-between flex-wrap m0c">
<div class="m0c flex flex-wrap justify-between">
<div efy_card class="w-auto!" style="padding: var(--efy_padding)">
<i18n-t keypath="titles.subscriptions" efy_card />{{ ": " + subscriptions.length }}
</div>
@ -12,15 +12,15 @@
id="fileSelector"
ref="fileSelector"
type="file"
class="display-none"
class="efy_hide_i"
multiple="multiple"
@change="importGroupsHandler"
/>
<label
for="fileSelector"
role="button"
v-text="`${$t('actions.import_from_json')} (${$t('titles.channel_groups')})`"
class="font-bold"
v-text="`${$t('actions.import_from_json')} (${$t('titles.channel_groups')})`"
/>
<button
@click="exportGroupsHandler"
@ -33,20 +33,26 @@
<button
v-for="group in channelGroups"
:key="group.groupName"
class="flex gap-[10rem] items-center"
class="flex items-center gap-[10rem]"
:class="{ selected: selectedGroup === group }"
@click="selectGroup(group)"
>
<span v-text="group.groupName !== '' ? group.groupName : $t('video.all')" />
<div v-if="group.groupName != '' && selectedGroup == group" class="flex flex-wrap gap-[10rem] items-center">
<div v-if="group.groupName != '' && selectedGroup == group" class="flex flex-wrap items-center gap-[10rem]">
<div>|</div>
<font-awesome-icon class="mx-2" icon="edit" @click="showEditGroupModal = true" />
<i class="i-fa6-solid:pen mx-2" @click="showEditGroupModal = true" />
<div>|</div>
<font-awesome-icon class="mx-2" icon="circle-minus" @click="deleteGroup(group)" />
<i class="i-fa6-solid:circle-minus mx-2" @click="groupToDelete = group.groupName" />
</div>
</button>
<button class="btn mx-1">
<font-awesome-icon icon="circle-plus" @click="showCreateGroupModal = true" />
<ConfirmModal
v-if="groupToDelete != null"
:message="$t('actions.delete_group_confirm')"
@close="groupToDelete = null"
@confirm="deleteGroup(groupToDelete)"
/>
<button class="btn mx-1" @click="showCreateGroupModal = true">
<i class="i-fa6-solid:circle-plus" />
</button>
</div>
<hr />
@ -67,13 +73,11 @@
</div>
</div>
<ModalComponent v-if="showCreateGroupModal" @close="showCreateGroupModal = !showCreateGroupModal">
<h2 v-t="'actions.create_group'" />
<div class="flex flex-col">
<input v-model="newGroupName" class="input my-4" type="text" :placeholder="$t('actions.group_name')" />
<button v-t="'actions.create_group'" class="btn ml-auto w-max" @click="createGroup()" />
</div>
</ModalComponent>
<CreateGroupModal
v-if="showCreateGroupModal"
:on-create-group="createGroup"
@close="showCreateGroupModal = false"
/>
<ModalComponent v-if="showEditGroupModal" @close="showEditGroupModal = false">
<div class="mb-5 mt-3 flex justify-between">
@ -90,7 +94,7 @@
<input
type="checkbox"
class="checkbox"
:checked="selectedGroup.channels.includes(subscription.url.substr(-11))"
:checked="selectedGroup.channels.includes(subscription.url.substr(-24))"
@change="checkedChange(subscription)"
/>
</div>
@ -100,37 +104,13 @@
</ModalComponent>
</template>
<style>
.pp-subs-cards {
display: grid;
gap: var(--efy_gap);
grid-template-columns: repeat(auto-fill, minmax(240rem, 1fr));
}
.pp-subs-card :is(a, span) {
-webkit-text-fill-color: var(--efy_text) !important;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.pp-subs-card button {
margin-bottom: 0;
width: 100%;
}
.selected {
}
.m0c {
gap: var(--efy_gap0);
}
.m0c :is(button, [role="button"]) {
margin: 0;
}
</style>
<script>
import ModalComponent from "./ModalComponent.vue";
import CreateGroupModal from "./CreateGroupModal.vue";
import ConfirmModal from "./ConfirmModal.vue";
export default {
components: { ModalComponent },
components: { ModalComponent, CreateGroupModal, ConfirmModal },
data() {
return {
subscriptions: [],
@ -141,55 +121,40 @@ export default {
channelGroups: [],
showCreateGroupModal: false,
showEditGroupModal: false,
newGroupName: "",
editedGroupName: "",
groupToDelete: null,
};
},
computed: {
filteredSubscriptions(_this) {
return _this.selectedGroup.groupName == ""
? _this.subscriptions
: _this.subscriptions.filter(channel => _this.selectedGroup.channels.includes(channel.url.substr(-11)));
: _this.subscriptions.filter(channel => _this.selectedGroup.channels.includes(channel.url.substr(-24)));
},
},
mounted() {
this.fetchSubscriptions().then(json => {
if (json.error) {
alert(json.error);
return;
}
this.subscriptions = json;
this.subscriptions.forEach(subscription => (subscription.subscribed = true));
});
this.channelGroups.push(this.selectedGroup);
if (!window.db) return;
const cursor = this.getChannelGroupsCursor();
cursor.onsuccess = e => {
const cursor = e.target.result;
if (cursor) {
const group = cursor.value;
this.channelGroups.push({
groupName: group.groupName,
channels: JSON.parse(group.channels),
});
cursor.continue();
}
};
this.loadChannelGroups();
},
activated() {
document.title = "Subscriptions - Piped";
},
methods: {
async fetchSubscriptions() {
if (this.authenticated) {
return await this.fetchJson(this.authApiUrl() + "/subscriptions", null, {
headers: {
Authorization: this.getAuthToken(),
},
});
} else {
return await this.fetchJson(this.authApiUrl() + "/subscriptions/unauthenticated", {
channels: this.getUnauthenticatedChannels(),
});
}
async loadChannelGroups() {
const groups = await this.getChannelGroups();
this.channelGroups.push(...groups);
},
handleButton(subscription) {
const channelId = subscription.url.split("/")[2];
@ -229,18 +194,16 @@ export default {
this.selectedGroup = group;
this.editedGroupName = group.groupName;
},
createGroup() {
if (!this.newGroupName || this.channelGroups.some(group => group.groupName == this.newGroupName)) return;
createGroup(newGroupName) {
if (!newGroupName || this.channelGroups.some(group => group.groupName == newGroupName)) return;
const newGroup = {
groupName: this.newGroupName,
groupName: newGroupName,
channels: [],
};
this.channelGroups.push(newGroup);
this.createOrUpdateChannelGroup(newGroup);
this.newGroupName = "";
this.showCreateGroupModal = false;
},
editGroupName() {
@ -259,12 +222,13 @@ export default {
this.showEditGroupModal = false;
},
deleteGroup(group) {
this.deleteChannelGroup(group.groupName);
this.channelGroups = this.channelGroups.filter(g => g != group);
this.selectedGroup = this.channelGroups[0];
this.deleteChannelGroup(group);
this.channelGroups = this.channelGroups.filter(g => g.groupName != group);
this.selectedGroup = this.channelGroups[0] || {};
this.groupToDelete = null;
},
checkedChange(subscription) {
const channelId = subscription.url.substr(-11);
const channelId = subscription.url.substr(-24);
this.selectedGroup.channels = this.selectedGroup.channels.includes(channelId)
? this.selectedGroup.channels.filter(channel => channel != channelId)
: this.selectedGroup.channels.concat(channelId);
@ -291,3 +255,29 @@ export default {
},
};
</script>
<style>
.pp-subs-cards {
display: grid;
gap: var(--efy_gap);
grid-template-columns: repeat(auto-fill, minmax(240rem, 1fr));
}
.pp-subs-card :is(a, span) {
-webkit-text-fill-color: var(--efy_text) !important;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.pp-subs-card button {
margin-bottom: 0;
width: 100%;
}
.selected {
}
.m0c {
gap: var(--efy_gap0);
}
.m0c :is(button, [role="button"]) {
margin: 0;
}
</style>

View file

@ -1,7 +1,7 @@
<template>
<div class="toast">
<slot />
<button v-t="'actions.dismiss'" @click="dismiss" class="m-0 mt-[10rem]" />
<button v-t="'actions.dismiss'" class="m-0 mt-[10rem]" @click="dismiss" />
</div>
</template>

View file

@ -19,7 +19,12 @@ export default {
};
},
mounted() {
if (this.$route.path == "/" && this.getPreferenceString("homepage", "trending") == "feed") return;
if (
this.$route.path == import.meta.env.BASE_URL &&
this.getPreferenceString("homepage", "trending") == "feed"
) {
return;
}
let region = this.getPreferenceString("region", "US");
this.fetchTrending(region).then(videos => {
@ -31,7 +36,7 @@ export default {
activated() {
document.title = this.$t("titles.trending") + " - Piped";
if (this.videos.length > 0) this.updateWatched(this.videos);
if (this.$route.path == "/") {
if (this.$route.path == import.meta.env.BASE_URL) {
let homepage = this.getHomePage(this);
if (homepage !== undefined) this.$router.push(homepage);
}

View file

@ -1,5 +1,5 @@
<template>
<div v-if="showVideo" class="video-card efy_trans_filter efy_shadow_trans">
<div v-if="showVideo" class="video-card efy_trans_filter efy_shadow_trans" :class="{ watched: item.watched }">
<!-- EFY-->
<router-link
class="video_item_link"
@ -9,6 +9,7 @@
v: item.url.substr(-11),
...(playlistId && { list: playlistId }),
...(index >= 0 && { index: index + 1 }),
...(preferListen && { listen: 1 }),
},
}"
>
@ -19,10 +20,22 @@
class="thumbnail"
loading="lazy"
/>
<div
v-if="item.duration > 0"
class="efy_shadow_trans efy_shadow_button_off efy_button_text_off pp-video-card-2 pp-time"
tabindex="-1"
v-text="timeFormat(item.duration)"
/>
<button
v-if="item.watched"
v-t="'video.watched'"
class="pp-video-card-2 pp-color pp-watched"
tabindex="-1"
/>
<!-- progress bar -->
<div
v-if="item.watched && item.duration > 0"
class="relative h-1 w-full"
class="watched_progress relative h-1 w-full"
style="
height: 4rem;
background: rgba(255, 255, 255, 0.067);
@ -42,120 +55,127 @@
box-shadow: 3rem 0 5rem #0005;
"
/>
<div
class="absolute bottom-0 left-0"
:style="{ height: `clamp(0%, ${(item.currentTime / item.duration) * 100}%, 100%` }"
/>
</div>
<div class="flex items-center h-[44rem] overflow-hidden">
<p v-text="title" class="pp-video-card-title" />
<div class="h-[44rem] flex items-center overflow-hidden">
<p class="pp-video-card-title" v-text="title" />
</div>
</router-link>
<div class="pp-video-card-buttons">
<button
v-if="item.duration > 0"
v-text="timeFormat(item.duration)"
class="efy_shadow_trans efy_shadow_button_off efy_button_text_off"
tabindex="-1"
/>
<button
v-if="item.views >= 0"
class="efy_shadow_trans efy_shadow_button_off efy_button_text_off"
tabindex="-1"
>
<font-awesome-icon icon="eye" style="margin-right: 5rem" />
<span v-text="`${numberFormat(item.views)}`" />
</button>
<div class="pp-card-info">
<div class="pp-video-card-2 h-[44rem] flex items-center overflow-hidden">
<p class="pp-video-card-title" v-text="title" />
</div>
<div class="pp-video-card-buttons">
<button
v-if="item.duration > 0"
class="pp-time efy_shadow_trans efy_shadow_button_off efy_button_text_off"
tabindex="-1"
v-text="timeFormat(item.duration)"
/>
<button
v-if="item.views >= 0"
class="efy_shadow_trans efy_shadow_button_off efy_button_text_off"
tabindex="-1"
>
<i class="i-fa6-solid:eye" style="margin-right: 5rem" />
<span v-text="`${numberFormat(item.views)}`" />
</button>
<router-link
class="btn efy_shadow_trans efy_shadow_button_off efy_button_text_off"
role="button"
:to="{
path: '/watch',
query: {
v: item.url.substr(-11),
...(playlistId && { list: playlistId }),
...(index >= 0 && { index: index + 1 }),
listen: '1',
},
}"
:aria-label="'Listen to ' + item.title"
:title="'Listen to ' + item.title"
>
<i :class="preferListen ? 'i-fa6-solid:tv' : 'i-fa6-solid:headphones'" />
</router-link>
<button
:title="$t('actions.add_to_playlist')"
class="btn efy_shadow_trans efy_shadow_button_off efy_button_text_off"
@click="showModal = !showModal"
>
<i class="i-fa6-solid:circle-plus" />
</button>
<button
v-if="admin"
ref="removeButton"
:title="$t('actions.remove_from_playlist')"
class="efy_shadow_trans efy_shadow_button_off efy_button_text_off"
@click="showConfirmRemove = true"
>
<i class="i-fa6-solid:circle-minus" />
</button>
<ConfirmModal
v-if="showConfirmRemove"
:message="$t('actions.delete_playlist_video_confirm')"
@close="showConfirmRemove = false"
@confirm="removeVideo(item.url.substr(-11))"
/>
<PlaylistAddModal
v-if="showModal"
:video-id="getVideoId()"
:video-info="video"
@close="showModal = !showModal"
/>
<ShareModal
v-if="showShareModal"
:video-id="getVideoId()"
:current-time="0"
@close="showShareModal = false"
/>
<button
v-if="item.uploaded > 0"
class="efy_shadow_trans efy_shadow_button_off efy_button_text_off"
v-text="timeAgo(item.uploaded)"
/>
<button v-else-if="item.uploadedDate" tabindex="-1" v-text="item.uploadedDate" />
<button v-if="item.isShort" v-t="'video.shorts'" class="pp-color" tabindex="-1" />
<button v-else-if="item.duration < 0" v-t="'video.live'" class="pp-color" tabindex="-1" />
<button v-if="item.watched" v-t="'video.watched'" class="pp-watched pp-color" tabindex="-1" />
</div>
<router-link
class="btn efy_shadow_trans efy_shadow_button_off efy_button_text_off"
role="button"
:to="{
path: '/watch',
query: {
v: item.url.substr(-11),
...(playlistId && { list: playlistId }),
...(index >= 0 && { index: index + 1 }),
listen: '1',
},
}"
:aria-label="'Listen to ' + item.title"
:title="'Listen to ' + item.title"
v-if="item.uploaderUrl && item.uploaderName && !hideChannel"
:to="item.uploaderUrl"
:title="item.uploaderName"
class="pp-video-card-channel"
>
<font-awesome-icon icon="headphones" />
<img
v-if="item.uploaderAvatar"
:src="item.uploaderAvatar"
loading="lazy"
class="efy_shadow_trans efy_shadow_button_off mt-0.5 h-36rem w-36rem"
width="36"
height="36"
/>
<div class="pp-text efy_shadow_trans efy_shadow_button_off">
<span v-text="item.uploaderName" />
<i v-if="item.uploaderVerified" class="i-fa6-solid:check ml-1.5" style="margin-right: 0" />
</div>
</router-link>
<button
:title="$t('actions.add_to_playlist')"
@click="showModal = !showModal"
class="btn efy_shadow_trans efy_shadow_button_off efy_button_text_off"
>
<font-awesome-icon icon="circle-plus" />
</button>
<button
v-if="admin"
ref="removeButton"
:title="$t('actions.remove_from_playlist')"
class="efy_shadow_trans efy_shadow_button_off efy_button_text_off"
@click="showConfirmRemove = true"
>
<font-awesome-icon icon="circle-minus" />
</button>
<ConfirmModal
v-if="showConfirmRemove"
:message="$t('actions.delete_playlist_video_confirm')"
@close="showConfirmRemove = false"
@confirm="removeVideo(item.url.substr(-11))"
/>
<PlaylistAddModal
v-if="showModal"
:video-id="item.url.substr(-11)"
:video-info="item"
@close="showModal = !showModal"
/>
<button
v-if="item.uploaded > 0"
class="efy_shadow_trans efy_shadow_button_off efy_button_text_off"
v-text="timeAgo(item.uploaded)"
/>
<button v-else-if="item.uploadedDate" v-text="item.uploadedDate" tabindex="-1" />
<button class="pp-color" v-if="item.isShort" v-t="'video.shorts'" tabindex="-1" />
<button v-else-if="item.duration < 0" v-t="'video.live'" class="pp-color" tabindex="-1" />
<button v-if="item.watched" v-t="'video.watched'" class="pp-color" tabindex="-1" />
</div>
<router-link
v-if="item.uploaderUrl && item.uploaderName && !hideChannel"
:to="item.uploaderUrl"
:title="item.uploaderName"
class="pp-video-card-channel"
>
<img
v-if="item.uploaderAvatar"
:src="item.uploaderAvatar"
loading="lazy"
class="mt-0.5 w-36rem h-36rem efy_shadow_trans efy_shadow_button_off"
width="36"
height="36"
/>
<div class="pp-text efy_shadow_trans efy_shadow_button_off">
<span v-text="item.uploaderName" />
<font-awesome-icon class="ml-1.5" v-if="item.uploaderVerified" icon="check" />
</div>
</router-link>
</div>
</template>
<style>
.shorts-img {
@apply w-full object-contain;
}
.video_item_link {
display: block;
}
</style>
<script>
import PlaylistAddModal from "./PlaylistAddModal.vue";
import ShareModal from "./ShareModal.vue";
import ConfirmModal from "./ConfirmModal.vue";
export default {
components: { PlaylistAddModal, ConfirmModal },
components: { PlaylistAddModal, ConfirmModal, ShareModal },
props: {
item: {
type: Object,
@ -172,12 +192,14 @@ export default {
hideChannel: { type: Boolean, default: false },
index: { type: Number, default: -1 },
playlistId: { type: String, default: null },
preferListen: { type: Boolean, default: false },
admin: { type: Boolean, default: false },
},
emits: ["remove"],
data() {
return {
showModal: false,
showPlaylistModal: false,
showShareModal: false,
showVideo: true,
showConfirmRemove: false,
};
@ -217,3 +239,13 @@ export default {
},
};
</script>
<style>
.shorts-img {
@apply w-full object-contain;
}
.video_item_link {
display: block;
position: relative;
}
</style>

View file

@ -2,7 +2,7 @@
<div
ref="container"
data-shaka-player-container
class="relative max-h-screen w-full flex justify-center efy_trans_filter_off"
class="efy_trans_filter_off relative max-h-screen w-full flex justify-center"
:class="{ 'player-container': !isEmbed }"
>
<video ref="videoEl" class="w-full" data-shaka-player :autoplay="shouldAutoPlay" :loop="selectedAutoLoop" />
@ -40,20 +40,32 @@
class="absolute top-8 rounded bg-black/80 p-2 text-lg backdrop-blur-sm"
/>
</div>
<ModalComponent v-if="showSpeedModal" @close="showSpeedModal = false">
<h2 v-t="'actions.playback_speed'" />
<div class="flex flex-col">
<input
v-model="playbackSpeedInput"
class="input my-3"
type="text"
:placeholder="$t('actions.playback_speed')"
@keyup.enter="setSpeedFromInput()"
/>
<button v-t="'actions.okay'" class="btn ml-auto w-min" @click="setSpeedFromInput()" />
</div>
</ModalComponent>
</template>
<script>
import "shaka-player/dist/controls.css";
import { parseTimeParam } from "@/utils/Misc";
import ModalComponent from "./ModalComponent.vue";
const shaka = import("shaka-player/dist/shaka-player.ui.js");
if (!window.muxjs) {
import("mux.js").then(muxjs => {
window.muxjs = muxjs;
});
}
const hotkeys = import("hotkeys-js");
export default {
components: { ModalComponent },
props: {
video: {
type: Object,
@ -79,6 +91,8 @@ export default {
destroying: false,
inSegment: false,
isHoveringTimebar: false,
showSpeedModal: false,
playbackSpeedInput: null,
currentTime: 0,
seekbarPadding: 2,
error: 0,
@ -119,7 +133,7 @@ export default {
this.hotkeysPromise.then(() => {
var self = this;
this.$hotkeys(
"f,m,j,k,l,c,space,up,down,left,right,0,1,2,3,4,5,6,7,8,9,shift+n,shift+,,shift+.,alt+p,return,.,,",
"f,m,j,k,l,c,space,up,down,left,right,0,1,2,3,4,5,6,7,8,9,shift+n,shift+s,shift+,,shift+.,alt+p,return,.,,",
function (e, handler) {
const videoEl = self.$refs.videoEl;
switch (handler.key) {
@ -209,11 +223,14 @@ export default {
self.$emit("navigateNext");
e.preventDefault();
break;
case "shift+s":
self.showSpeedModal = true;
break;
case "shift+,":
self.$player.trickPlay(Math.max(videoEl.playbackRate - 0.25, 0.25));
self.adjustPlaybackSpeed(videoEl.playbackRate - 0.25);
break;
case "shift+.":
self.$player.trickPlay(Math.min(videoEl.playbackRate + 0.25, 2));
self.adjustPlaybackSpeed(videoEl.playbackRate + 0.25);
break;
case "alt+p":
document.pictureInPictureElement
@ -253,32 +270,6 @@ export default {
videoEl.setAttribute("poster", this.video.thumbnailUrl);
const time = this.$route.query.t ?? this.$route.query.start;
if (time) {
videoEl.currentTime = parseTimeParam(time);
this.initialSeekComplete = true;
} else if (window.db && this.getPreferenceBoolean("watchHistory", false)) {
var tx = window.db.transaction("watch_history", "readonly");
var store = tx.objectStore("watch_history");
var request = store.get(this.video.id);
request.onsuccess = function (event) {
var video = event.target.result;
const currentTime = video?.currentTime;
if (currentTime) {
if (currentTime < component.video.duration * 0.9) {
videoEl.currentTime = currentTime;
}
}
};
tx.oncomplete = () => {
this.initialSeekComplete = true;
};
} else {
this.initialSeekComplete = true;
}
const noPrevPlayer = !this.$player;
var streams = [];
@ -342,11 +333,12 @@ export default {
}
if (noPrevPlayer)
this.shakaPromise.then(() => {
this.shakaPromise.then(async () => {
if (this.destroying) return;
this.$shaka.polyfill.installAll();
const localPlayer = new this.$shaka.Player(videoEl);
const localPlayer = new this.$shaka.Player();
await localPlayer.attach(videoEl);
const proxyURL = new URL(component.video.proxyUrl);
let proxyPath = proxyURL.pathname;
if (proxyPath.lastIndexOf("/") === proxyPath.length - 1) {
@ -435,7 +427,7 @@ export default {
videoEl.currentTime = segment.segment[1];
segment.skipped = true;
},
setPlayerAttrs(localPlayer, videoEl, uri, mime, shaka) {
async setPlayerAttrs(localPlayer, videoEl, uri, mime, shaka) {
const url = "/watch?v=" + this.video.id;
if (!this.$ui) {
@ -481,14 +473,7 @@ export default {
this.$ui = new shaka.ui.Overlay(localPlayer, this.$refs.container, videoEl);
const overflowMenuButtons = [
"quality",
"language",
"captions",
"picture_in_picture",
"playback_rate",
"airplay",
];
const overflowMenuButtons = ["quality", "captions", "picture_in_picture", "playback_rate", "airplay"];
if (this.isEmbed) {
overflowMenuButtons.push("open_new_tab");
@ -499,7 +484,7 @@ export default {
seekBarColors: {
base: "rgba(255, 255, 255, 0.3)",
buffered: "rgba(255, 255, 255, 0.54)",
played: `oklch(var(--efy_color1_var))`,
played: "var(--efy_piped_color1)",
},
};
@ -519,6 +504,8 @@ export default {
const disableVideo = this.getPreferenceBoolean("listen", false) && !this.video.livestream;
const prefetchLimit = Math.min(Math.max(this.getPreferenceNumber("prefetchLimit", 2), 0), 10);
this.$player.configure({
preferredVideoCodecs: this.preferredVideoCodecs,
preferredAudioCodecs: ["opus", "mp4a"],
@ -526,7 +513,12 @@ export default {
disableVideo: disableVideo,
},
streaming: {
segmentPrefetchLimit: 10,
segmentPrefetchLimit: prefetchLimit,
retryParameters: {
maxAttempts: Infinity,
baseDelay: 250,
backoffFactor: 1.5,
},
},
});
@ -535,8 +527,39 @@ export default {
quality > 0 && (this.video.audioStreams.length > 0 || this.video.livestream) && !disableVideo;
if (qualityConds) this.$player.configure("abr.enabled", false);
const time = this.$route.query.t ?? this.$route.query.start;
var startTime = 0;
if (time) {
startTime = parseTimeParam(time);
this.initialSeekComplete = true;
} else if (window.db && this.getPreferenceBoolean("watchHistory", false)) {
await new Promise(resolve => {
var tx = window.db.transaction("watch_history", "readonly");
var store = tx.objectStore("watch_history");
var request = store.get(this.video.id);
request.onsuccess = function (event) {
var video = event.target.result;
const currentTime = video?.currentTime;
if (currentTime) {
if (currentTime < video.duration * 0.9) {
startTime = currentTime;
}
}
resolve();
};
tx.oncomplete = () => {
this.initialSeekComplete = true;
};
});
} else {
this.initialSeekComplete = true;
}
player
.load(uri, 0, mime)
.load(uri, startTime, mime)
.then(() => {
const isSafari = window.navigator?.vendor?.includes("Apple");
@ -553,6 +576,18 @@ export default {
player.selectAudioLanguage(lang);
}
const audioLanguages = player.getAudioLanguages();
if (audioLanguages.length > 1) {
const overflowMenuButtons = this.$ui.getConfiguration().overflowMenuButtons;
// append language menu on index 1
const newOverflowMenuButtons = [
...overflowMenuButtons.slice(0, 1),
"language",
...overflowMenuButtons.slice(1),
];
this.$ui.configure("overflowMenuButtons", newOverflowMenuButtons);
}
if (qualityConds) {
var leastDiff = Number.MAX_VALUE;
var bestStream = null;
@ -603,6 +638,16 @@ export default {
const autoDisplayCaptions = this.getPreferenceBoolean("autoDisplayCaptions", false);
this.$player.setTextTrackVisibility(autoDisplayCaptions);
const prefSubtitles = this.getPreferenceString("subtitles", "");
if (prefSubtitles !== "") {
const textTracks = this.$player.getTextTracks();
const subtitleIdx = textTracks.findIndex(textTrack => textTrack.language == prefSubtitles);
if (subtitleIdx != -1) {
this.$player.setTextTrackVisibility(true);
this.$player.selectTextTrack(textTracks[subtitleIdx]);
}
}
})
.catch(e => {
console.error(e);
@ -636,7 +681,19 @@ export default {
this.$refs.videoEl.currentTime = time;
}
},
adjustPlaybackSpeed(newSpeed) {
const normalizedSpeed = Math.min(4, Math.max(0.25, newSpeed));
this.$player.trickPlay(normalizedSpeed);
},
setSpeedFromInput() {
try {
const newSpeed = Number(this.playbackSpeedInput);
this.adjustPlaybackSpeed(newSpeed);
} catch (err) {
alert(this.$t("actions.invalid_input"));
}
this.showSpeedModal = false;
},
updateMarkers() {
const markers = this.$refs.container.querySelector(".shaka-ad-markers");
const array = ["to right"];
@ -874,6 +931,11 @@ html .shaka-range-element:focus {
.shaka-settings-menu button {
-webkit-text-fill-color: var(--efy_text) !important;
margin: 1.6rem 0 !important;
place-content: start;
width: 100%;
.shaka-overflow-menu-only {
width: fit-content;
}
}
.shaka-overflow-menu .material-icons-round,
.shaka-settings-menu .material-icons-round {

View file

@ -16,14 +16,9 @@ export default {
<template>
<template v-if="getPreferenceBoolean('showWatchOnYouTube', false)">
<a
:href="link"
role="button"
class="pp-square flex items-center justify-center"
:aria-label="'Watch on Odysee'"
:title="`${$t('player.watch_on')}${platform}`"
>
<font-awesome-icon class="mx-1.5" :icon="['fab', platform.toLowerCase()]" />
<a :href="link" role="button" class="pp-square flex items-center" style="margin: 0; padding: 0">
<i v-if="platform == 'YouTube'" class="i-fa6-brands:youtube m-0" />
<i v-else-if="platform == 'Odysee'" class="i-fa6-brands:odysee m-0" />
</a>
</template>
</template>

View file

@ -10,7 +10,7 @@
/>
</div>
<LoadingIndicatorPage :show-content="video && !isEmbed" class="w-full mt-[15rem]">
<LoadingIndicatorPage :show-content="video && !isEmbed" class="mt-[15rem] w-full">
<ErrorHandler v-if="video && video.error" :message="video.message" :error="video.error" />
<Transition>
<ToastComponent v-if="shouldShowToast" @dismissed="dismiss">
@ -46,7 +46,7 @@
<!-- views / date -->
<div class="flex flex-auto">
<span v-t="{ path: 'video.views', args: { views: addCommas(video.views) } }" />
<span> </span>
<span> · </span>
<span v-text="uploadDate" />
</div>
<!-- Likes/dilikes -->
@ -77,21 +77,22 @@
video.uploader
}}</router-link>
<!-- Verified Badge -->
<font-awesome-icon v-if="video.uploaderVerified" class="ml-1" icon="check" />
<i v-if="video.uploaderVerified" class="i-fa6-solid:check ml-1" />
</div>
<div class="pp-watch-buttons">
<!-- Subscribe button -->
<button
v-t="{
path: `actions.${subscribed ? 'unsubscribe' : 'subscribe'}`,
args: { count: numberFormat(video.uploaderSubscriberCount) },
}"
class="btn"
@click="subscribeHandler"
v-text="
$t('actions.' + (subscribed ? 'unsubscribe' : 'subscribe')) +
' - ' +
numberFormat(video.uploaderSubscriberCount)
"
/>
<!-- Playlist Add button -->
<button class="btn flex items-center" @click="showModal = !showModal">
{{ $t("actions.add_to_playlist") }}<font-awesome-icon class="ml-1" icon="circle-plus" />
<button class="pp-square btn flex items-center" style="padding: 0" @click="showModal = !showModal">
<i class="i-fa6-solid:circle-plus m-0" />
</button>
<PlaylistAddModal
v-if="showModal"
@ -108,9 +109,12 @@
:playlist-index="index"
@close="showShareModal = !showShareModal"
/>
<button class="btn flex items-center share-btn" @click="showShareModal = !showShareModal">
<font-awesome-icon class="mx-1.5 mr-1" icon="fa-share" />
<i18n-t keypath="actions.share" tag="strong"></i18n-t>
<button
class="pp-square btn share-btn flex items-center"
style="padding: 0"
@click="showShareModal = !showShareModal"
>
<i class="i-fa6-solid:share m-0" />
</button>
<!-- YouTube -->
<WatchOnButton :link="`https://youtu.be/${getVideoId()}`" />
@ -123,8 +127,9 @@
:aria-label="(isListening ? 'Watch ' : 'Listen to ') + video.title"
:title="(isListening ? 'Watch ' : 'Listen to ') + video.title"
class="pp-square btn flex items-center"
style="padding: 0"
>
<font-awesome-icon class="mx-1.5" :icon="isListening ? 'tv' : 'headphones'" />
<i :class="isListening ? 'i-fa6-solid:tv' : 'i-fa6-solid:headphones'" class="m-0" />
</router-link>
<!-- RSS Feed button -->
<a
@ -135,11 +140,12 @@
:href="`${apiUrl()}/feed/unauthenticated/rss?channels=${video.uploaderUrl.split('/')[2]}`"
target="_blank"
class="pp-square btn flex items-center"
style="padding: 0"
>
<font-awesome-icon class="mx-1.5" icon="rss" />
<i class="i-fa6-solid:rss m-0" />
</a>
<button class="btn flex items-center gap-1 <md:hidden" @click="downloadCurrentFrame">
<i class="i-fa6-solid:download" />{{ $t("actions.download_frame") }}
<button class="pp-square btn flex items-center" style="padding: 0" @click="downloadCurrentFrame">
<i class="i-fa6-solid:download m-0" />
</button>
</div>
</div>
@ -163,8 +169,8 @@
<label v-t="'actions.show_description'" for="showDesc" />
<input id="showComments" v-model="showComments" type="checkbox" @click="toggleComments" />
<label
v-text="`${$t('actions.show_comments')} - ${numberFormat(comments?.commentCount)}`"
for="showComments"
v-text="`${$t('actions.show_comments')} - ${numberFormat(comments?.commentCount)}`"
/>
<input id="showRecs" v-model="showRecs" type="checkbox" />
<label v-t="'actions.show_recommendations'" for="showRecs" />
@ -195,7 +201,7 @@
<router-link
v-for="tag in video.tags"
:key="tag"
class="line-clamp-1 efy_trans_filter efy_shadow_trans"
class="efy_trans_filter efy_shadow_trans line-clamp-1"
:to="`/results?search_query=${encodeURIComponent(tag)}`"
>{{ tag }}</router-link
>
@ -219,6 +225,7 @@
:key="comment.commentId"
:comment="comment"
:uploader="video.uploader"
:uploader-avatar-url="video.uploaderAvatar"
:video-id="getVideoId()"
class="efy_trans_filter efy_shadow_trans"
/>
@ -230,6 +237,7 @@
:playlist-id="playlistId"
:playlist="playlist"
:selected-index="index"
:prefer-listen="isListening"
/>
<div v-show="showRecs" class="pp-show-recs">
<h6 efy_card style="padding: 5rem 10rem 3rem; margin: 0">Recommended</h6>
@ -237,6 +245,8 @@
v-for="related in video.relatedStreams"
:key="related.url"
:item="related"
:prefer-listen="isListening"
class="mb-4"
height="94"
width="168"
/>
@ -287,7 +297,7 @@ export default {
selectedAutoLoop: false,
selectedAutoPlay: null,
showComments: true,
showDesc: true,
showDesc: false,
showRecs: true,
showChapters: true,
comments: null,
@ -388,7 +398,7 @@ export default {
this.active = true;
this.selectedAutoPlay = this.getPreferenceBoolean("autoplay", false);
this.showComments = !this.getPreferenceBoolean("minimizeComments", false);
this.showDesc = !this.getPreferenceBoolean("minimizeDescription", false);
this.showDesc = !this.getPreferenceBoolean("minimizeDescription", true);
this.showRecs = !this.getPreferenceBoolean("minimizeRecommendations", false);
this.showChapters = !this.getPreferenceBoolean("minimizeChapters", false);
if (this.video?.duration) {
@ -428,7 +438,7 @@ export default {
});
sponsors?.segments?.forEach(segment => {
const option = skipOptions[segment.category];
const option = skipOptions?.[segment.category];
segment.autoskip = option === undefined || option === "auto";
});
@ -480,9 +490,7 @@ export default {
},
async getPlaylistData() {
if (this.playlistId) {
await this.fetchJson(this.apiUrl() + "/playlists/" + this.playlistId).then(data => {
this.playlist = data;
});
this.playlist = await this.getPlaylist(this.playlistId);
await this.fetchPlaylistPages().then(() => {
if (!(this.index >= 0)) {
for (let i = 0; i < this.playlist.relatedStreams.length; i++)
@ -516,65 +524,17 @@ export default {
this.fetchSponsors().then(data => (this.sponsors = data));
},
async getComments() {
this.fetchComments().then(data => {
this.rewriteComments(data.comments);
this.comments = data;
});
this.comments = await this.fetchComments();
},
async fetchSubscribedStatus() {
if (!this.channelId) return;
if (!this.authenticated) {
this.subscribed = this.isSubscribedLocally(this.channelId);
return;
}
this.fetchJson(
this.authApiUrl() + "/subscribed",
{
channelId: this.channelId,
},
{
headers: {
Authorization: this.getAuthToken(),
},
},
).then(json => {
this.subscribed = json.subscribed;
});
},
rewriteComments(data) {
data.forEach(comment => {
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(comment.commentText, "text/html");
xmlDoc.querySelectorAll("a").forEach(elem => {
if (!elem.innerText.match(/(?:[\d]{1,2}:)?(?:[\d]{1,2}):(?:[\d]{1,2})/))
elem.outerHTML = elem.getAttribute("href");
});
comment.commentText = xmlDoc
.querySelector("body")
.innerHTML.replaceAll(/(?:http(?:s)?:\/\/)?(?:www\.)?youtube\.com(\/[/a-zA-Z0-9_?=&-]*)/gm, "$1")
.replaceAll(
/(?:http(?:s)?:\/\/)?(?:www\.)?youtu\.be\/(?:watch\?v=)?([/a-zA-Z0-9_?=&-]*)/gm,
"/watch?v=$1",
);
});
this.subscribed = await this.fetchSubscriptionStatus(this.channelId);
},
subscribeHandler() {
if (this.authenticated) {
this.fetchJson(this.authApiUrl() + (this.subscribed ? "/unsubscribe" : "/subscribe"), null, {
method: "POST",
body: JSON.stringify({
channelId: this.channelId,
}),
headers: {
Authorization: this.getAuthToken(),
"Content-Type": "application/json",
},
});
} else {
if (!this.handleLocalSubscriptions(this.channelId)) return;
}
this.subscribed = !this.subscribed;
this.toggleSubscriptionState(this.channelId, this.subscribed).then(success => {
if (success) this.subscribed = !this.subscribed;
});
},
handleClick(event) {
if (!event || !event.target) return;
@ -614,12 +574,17 @@ export default {
}).then(json => {
this.comments.nextpage = json.nextpage;
this.loading = false;
this.rewriteComments(json.comments);
this.comments.comments = this.comments.comments.concat(json.comments);
});
}
},
getVideoId() {
if (this.$route.query.video_ids) {
const videos_list = this.$route.query.video_ids.split(",");
this.index = Number(this.$route.query.index ?? 0);
return videos_list[this.index];
}
return this.$route.query.v || this.$route.params.v;
},
navigate(time) {
@ -659,7 +624,15 @@ export default {
},
navigateNext() {
const params = this.$route.query;
let url = this.playlist?.relatedStreams?.[this.index]?.url ?? this.video.relatedStreams[0].url;
const video_ids = this.$route.query.video_ids?.split(",") ?? [];
let url;
if (this.playlist) {
url = this.playlist?.relatedStreams?.[this.index]?.url ?? this.video.relatedStreams[0].url;
} else if (video_ids.length > this.index + 1) {
url = `${this.$route.path}?index=${this.index + 1}`;
} else {
url = this.video.relatedStreams[0].url;
}
const searchParams = new URLSearchParams();
for (var param in params)
switch (param) {
@ -667,7 +640,8 @@ export default {
case "t":
break;
case "index":
if (this.index < this.playlist.relatedStreams.length) searchParams.set("index", this.index + 1);
if (this.playlist && this.index < this.playlist.relatedStreams.length)
searchParams.set("index", this.index + 1);
break;
case "list":
if (this.index < this.playlist.relatedStreams.length) searchParams.set("list", params.list);
@ -719,6 +693,39 @@ export default {
margin: 0;
}
}
video::-webkit-media-text-track-display {
display: flex;
width: fit-content !important;
position: relative !important;
top: calc(100% - 150rem) !important;
height: fit-content !important;
padding: 2rem 8rem;
margin: auto;
margin-bottom: 8rem;
background: #0008 !important;
backdrop-filter: blur(20rem);
color: #fff;
border-radius: var(--efy_radius);
font-family: var(--efy_font_family);
font-size: 22rem !important;
}
video::cue {
background: transparent;
}
.player-container.pp-trans video::-webkit-media-text-track-display {
background: transparent !important;
backdrop-filter: none;
margin-bottom: unset;
line-height: 1.2;
text-shadow: 0 0 5rem #000;
}
.player-container.pp-solid video::-webkit-media-text-track-display {
background: var(--efy_bg) !important;
color: var(--efy_text);
backdrop-filter: none;
}
@media (width <= 768px) {
.share-btn {
aspect-ratio: 1;
@ -730,4 +737,10 @@ export default {
margin: 0;
}
}
@media (max-width: 639px) {
video::-webkit-media-text-track-display {
font-size: 16rem !important;
top: calc(100% - 120rem) !important;
}
}
</style>

View file

@ -5,44 +5,46 @@
"register": "إنشاء حساب",
"preferences": "الإعدادات",
"history": "سجل المشاهدة",
"subscriptions": "الاشتراكات",
"subscriptions": "الإشتراكات",
"playlists": "قوائم التشغيل",
"feed": "محتوى الاشتراكات",
"feed": "محتوى الإشتراكات",
"account": "الحساب",
"instance": "الخادم",
"player": "المشغل",
"livestreams": "البث المباشر",
"livestreams": "البثوث المباشرة",
"channels": "القنوات",
"bookmarks": "الاشارات المرجعيه",
"bookmarks": "الإشارات المرجعية",
"channel_groups": "مجموعات القنوات",
"dearrow": "دي ارو"
"dearrow": "دي ارو",
"albums": "الألبومات",
"custom_instances": "مثيلات مخصصة"
},
"player": {
"watch_on": "مشاهدة على {0}",
"failed": "فشل مع رمز الخطأ {0}، راجع السجلات لمزيد من المعلومات"
},
"actions": {
"subscribe": "اشتراك - {count}",
"view_subscriptions": "عرض الاشتراكات",
"subscribe": "إشتراك",
"view_subscriptions": "عرض الإشتراكات",
"most_recent": "الأحدث",
"least_recent": "الأقدم",
"unsubscribe": "إلغاء اشتراك - {count}",
"unsubscribe": "إلغاء الإشتراك",
"channel_name_asc": "إسم القناة (أبجدي تصاعدي)",
"sort_by": "ترتيب النتائج:",
"back": "رجوع",
"skip_intro": "تخطي الفواصل/ المقدمة",
"light": "مضيء",
"clear_history": "مسح تاريخ المشاهدات",
"hide_replies": "إخفاء التعليقات",
"create_playlist": "إنشاء قائمة",
"delete_playlist": "مسح القائمة",
"select_playlist": "اختر قائمة",
"light": "فاتح",
"clear_history": "مسح سجل المشاهدات",
"hide_replies": "إخفاء الردود",
"create_playlist": "إنشاء قائمة تشغيل",
"delete_playlist": "حذف قائمة التسجيل",
"select_playlist": "اختر قائمة تسجيل",
"delete_playlist_confirm": "حذف قائمة التشغيل هذه؟",
"please_select_playlist": "فضلًا اختر قائمة",
"please_select_playlist": "فضلًا اختر قائمة تشغيل",
"channel_name_desc": "إسم القناة (أبجدي تنازلي)",
"uses_api_from": "اختيار المُشغل: ",
"skip_sponsors": "تخطي الإعلان",
"enable_sponsorblock": "تفعيل مانع الإعلانات",
"uses_api_from": "استخدامات واجهة برمجة التطبيقات من • ",
"skip_sponsors": "تخطي الرعايات",
"enable_sponsorblock": "تفعيل حظر الإعلانات",
"auto": "تلقائي",
"dark": "داكن",
"search": "‏بحث (Ctrl+K)",
@ -54,7 +56,7 @@
"skip_interaction": "تخطي تذكير التفاعل (اشتراك)",
"skip_non_music": "تخطي الموسيقى: قسم غير الموسيقى",
"theme": "السمة",
"instance_selection": "قائمة الخوادم",
"instance_selection": "الخادم",
"export_to_json": "تصدير إلى JSON",
"show_more": "اظهار المزيد",
"skip_outro": "تخطي بطاقات النهاية / الاعتمادات",
@ -67,23 +69,23 @@
"country_selection": "البلد",
"default_homepage": "الصفحة الرئيسية الافتراضية",
"show_comments": "إظهار التعليقات",
"minimize_description_default": "تصغير الوصف بشكل افتراضي",
"minimize_description_default": "إخفاء الوصف بشكل افتراضي",
"store_watch_history": "تخزين سجل المشاهدة",
"language_selection": "اللغة",
"instances_list": "قائمة المثيلات",
"instances_list": "قائمة الخوادم",
"enabled_codecs": "برامج الترميز الممكنة (متعددة)",
"import_from_json": "استيراد من JSON",
"loop_this_video": "تكرار هذا الفيديو",
"auto_play_next_video": "التشغيل التلقائي للفيديو التالي",
"auto_play_next_video": "تشغيل الفيديو التالي تلقائيا",
"donations": "التبرعات للتطوير",
"minimize_description": "تصغير الوصف",
"show_description": "عرض الوصف",
"minimize_recommendations": "تقليل التوصيات",
"minimize_description": "إخفاء الوصف",
"show_description": "إظهار الوصف",
"minimize_recommendations": "إخفاء التوصيات",
"show_recommendations": "إظهار التوصيات",
"disable_lbry": "تعطيل LBRY للبث",
"enable_lbry_proxy": "تمكين الوكيل ل LBRY",
"enable_lbry_proxy": "تمكين الوكيل لـ LBRY",
"view_ssl_score": "عرض نقاط طبقة المقابس الآمنة (SSL)",
"loading": "تحميل...",
"loading": "جارٍ التحميل...",
"filter": "المرشحات",
"load_more_replies": "تحميل المزيد من الردود",
"add_to_playlist": "إضافة إلى قائمة التشغيل",
@ -91,17 +93,17 @@
"delete_playlist_video_confirm": "إزالة الفيديو من قائمة التشغيل؟",
"delete_account": "حذف الحساب",
"logout": "تسجيل الخروج من هذا الجهاز",
"minimize_recommendations_default": "تقليل التوصيات بشكل افتراضي",
"minimize_recommendations_default": "إخفاء التوصيات بشكل افتراضي",
"invalidate_session": "تسجيل الخروج من جميع الأجهزة",
"different_auth_instance": "استخدام مثيل مختلف للمصادقة",
"different_auth_instance": "استخدام خادم مختلف للمصادقة",
"instance_auth_selection": "خادم المصادقة",
"clone_playlist": "استنساخ قائمة التشغيل",
"clone_playlist_success": "تم استنساخها بنجاح!",
"download_as_txt": "تنزيل بتنسيق .txt",
"reset_preferences": "اعادة التعيين للتفضيلات",
"confirm_reset_preferences": "هل أنت متأكد من أنك تريد إعادة تعيين تفضيلاتك؟",
"backup_preferences": "تفضيلات النسخ الاحتياطي",
"restore_preferences": "استعادة التفضيلات",
"reset_preferences": "إعادة التعيين الإعدادات",
"confirm_reset_preferences": "هل أنت متأكد من أنك تريد إعادة تعيين إعداداتك؟",
"backup_preferences": "النسخ الاحتياطي للإعدادات",
"restore_preferences": "إستعادة الإعدادات",
"back_to_home": "العودة إلى الصفحة الرئيسية",
"share": "مشاركة",
"with_timecode": "شارك مع رمز الوقت",
@ -114,17 +116,17 @@
"documentation": "التوثيق",
"status_page": "الحالة",
"source_code": "شفرة المصدر",
"instance_donations": "تبرعات المثيل",
"hide_watched": "إخفاء مقاطع الفيديو التي تمت مشاهدتها من الخلاصة",
"instance_donations": "تبرعات للخادم",
"hide_watched": "إخفاء مقاطع الفيديو التي تمت المشاهدة من محتوى الإشتراكات",
"reply_count": "{count} الردود",
"minimize_comments_default": "تصغير التعليقات بشكل افتراضي",
"minimize_comments": "تصغير التعليقات",
"minimize_comments_default": "إخفاء التعليقات بشكل افتراضي",
"minimize_comments": "إخفاء التعليقات",
"show_watch_on_youtube": "عرض زر مشاهدة على يوتيوب",
"minimize_chapters_default": "تصغير الفصول بشكل افتراضي",
"minimize_chapters_default": "إخفاء الفصول بشكل افتراضي",
"no_valid_playlists": "لا يحتوي الملف على قوائم تشغيل صالحة!",
"with_playlist": "المشاركة مع قائمة التشغيل",
"bookmark_playlist": "الاشاره المرجعيه",
"playlist_bookmarked": "تم وضعها في الاشارات المرجعية",
"bookmark_playlist": "الإشارة المرجعية",
"playlist_bookmarked": "تم وضعها في الإشارة المرجعية",
"skip_button_only": "إظهار زر التخطي",
"skip_automatically": "تلقائيا",
"min_segment_length": "الحد الأدنى لطول الفصل (بالثواني)",
@ -143,20 +145,31 @@
"show_search_suggestions": "إظهار اقتراحات البحث",
"chapters_layout_mobile": "تخطيط الفصول على الهاتف",
"delete_automatically": "الحذف تلقائيا بعد",
"enable_dearrow": "تمكين دي ارو",
"enable_dearrow": "تمكين DeArrow",
"generate_qrcode": "إنشاء رمز الاستجابة السريعة",
"import_from_json_csv": "استيراد من JSON/CSV",
"download_frame": "إطار التحميل",
"instance_privacy_policy": "سياسة الخصوصية"
"instance_privacy_policy": "سياسة الخصوصية",
"add_to_group": "إضافة إلى المجموعة",
"instances_not_shown": "الخوادم العامة غير المعروضة هنا ليست متاحة حاليًا.",
"concurrent_prefetch_limit": "حد الجلب المسبق للدفق المتزامن",
"customize": "تخصيص",
"invalid_url": "عنوان URL غير صالح!",
"add": "إضافة",
"delete_group_confirm": "حذف هذه المجموعة؟",
"creator_replied": "أجاب المنشء",
"creator_liked": "المنشء اعجب",
"playback_speed": "سرعة التشغيل",
"invalid_input": "مدخل غير صالح"
},
"video": {
"sponsor_segments": "المقاطع الإعلانية",
"ratings_disabled": "التقييم غير متاح",
"chapters": "فصول الفيديو",
"watched": "تمت مشاهدته",
"watched": "تمت المشاهدة",
"views": "{views} عدد المشاهدات",
"shorts": "فديوهات قصيرة",
"videos": "الفيديوات",
"shorts": "مقاطع فديو قصيرة",
"videos": "مقاطع الفيديو",
"live": "{0} مباشر",
"all": "الكل",
"category": "الفئة",
@ -175,20 +188,22 @@
"did_you_mean": "هل تقصد: {0}؟",
"music_playlists": "YT Music: قوائم التشغيل",
"music_albums": "YT Music: ألبومات",
"music_artists": "YT الموسيقى: الفنانين"
"music_artists": "YT Music: الفنانين"
},
"preferences": {
"version": "الإصدار",
"registered_users": "المستخدمون المسجلون",
"instance_name": "اسم المثيل",
"instance_locations": "مواقع المثيل",
"instance_name": "أسم الخادم",
"instance_locations": "مواقع الخادم",
"has_cdn": "لديه CDN؟",
"ssl_score": "نقاط طبقة المقابس الآمنة",
"up_to_date": "حديث؟"
"up_to_date": "‏محدث؟",
"uptime_30d": "وقت التشغيل (30 يومًا)",
"api_url": "رابط واجهة برمجة التطبيقات"
},
"comment": {
"pinned_by": "مثبت بواسطة {author}",
"disabled": "يتم تعطيل التعليقات بواسطة القائم بالتحميل.",
"disabled": "يتم تعطيل التعليقات بواسطة القائم بالرفع.",
"user_disabled": "التعليقات معطلة في الإعدادات.",
"loading": "تحميل التعليقات..."
},
@ -205,16 +220,18 @@
"preferences_note": "ملاحظة: يتم حفظ التفضيلات في وحدة التخزين المحلية في متصفحك. سيؤدي حذف بيانات المتصفح إلى إعادة تعيينها."
},
"info": {
"preferences_note": "ملاحظة: يتم حفظ التفضيلات في وحدة التخزين المحلية في متصفحك. سيؤدي حذف بيانات المتصفح إلى إعادة تعيينها.",
"preferences_note": "ملاحظة: يتم حفظ الإعدادات في وحدة التخزين المحلية في متصفحك. حذف بيانات متصفحك سيؤدي إلى إعادة تعيينها.",
"page_not_found": "لم يتم العثور على الصفحة",
"copied": "نسخ!",
"cannot_copy": "لا يمكن نسخه!",
"local_storage": "يتطلب هذا الإجراء التخزين المحلي، هل يتم تمكين ملفات تعريف الارتباط؟",
"register_no_email_note": "لا ينصح باستخدام البريد الإلكتروني كاسم مستخدم. المضي قدما على أي حال؟",
"next_video_countdown": "تشغيل الفيديو التالي بعد { 0 } ق",
"next_video_countdown": "تشغيل الفيديو التالي بعد {0} ث",
"weeks": "{amount} أسبوع (أسابيع)",
"hours": "{amount} ساعة (ساعات)",
"months": "{amount} شهر (أشهر)",
"days": "{amount} يوم (أيام)"
"days": "{amount} يوم (أيام)",
"login_note": "سجل الدخول باستخدام حساب تم إنشاؤه في هذا الخادم.",
"register_note": "سجل حسابًا لخادم Piped هذا. سيسمح لك هذا بمزامنة اشتراكاتك وقوائم التشغيل مع حسابك، بحيث يتم تخزينها من جانب الخادم. يمكنك استخدام جميع الميزات بدون حساب، ولكن سيتم تخزين جميع البيانات في ذاكرة التخزين المؤقت المحلية لمتصفحك. يُرجى التأكد من عدم استخدام عنوان البريد الإلكتروني كاسم المستخدم الخاص بك واختيار كلمة مرور آمنة لا تستخدمها في أي مكان آخر."
}
}

View file

@ -21,8 +21,8 @@
"watch_on": "{0} saytında bax"
},
"actions": {
"subscribe": "Abunə Ol - {count}",
"unsubscribe": "Abunəlikdən Çıx - {count}",
"subscribe": "Abunə Ol",
"unsubscribe": "Abunəlikdən Çıx",
"view_subscriptions": "Abunəliklərə Baxın",
"sort_by": "Çeşidlə:",
"most_recent": "Ən Yeni",

57
src/locales/be.json Normal file
View file

@ -0,0 +1,57 @@
{
"actions": {
"okay": "Добра",
"reply_count": "{count} адказаў",
"skip_button_only": "Паказаць кнопку прапусціць",
"channel_name_asc": "Імя канала (А-Я)",
"download_as_txt": "Спампаваць як .txt",
"subscribe": "Падпісацца",
"loading": "Загрузка...",
"filter": "Фільтар",
"unsubscribe": "Адпісацца",
"channel_name_desc": "Імя канала (Я-А)",
"language_selection": "Мова",
"show_less": "Паказаць менш",
"theme": "Тэма",
"hide_replies": "Схаваць адказы",
"least_recent": "Найменш актуальныя",
"most_recent": "Самыя актуальныя",
"no": "Не",
"documentation": "Дакументацыя",
"sort_by": "Сартаваць па:",
"back": "Назад",
"view_subscriptions": "Паказаць падпіскі",
"status_page": "Статус",
"import_from_json": "Імпартаваць з JSON",
"instance_privacy_policy": "Палітыка прыватнасці",
"bookmark_playlist": "Закладка",
"skip_outro": "Прапусціць канчатковыя цітры/тытры",
"skip_intro": "Прапусціць паўзу/застаўку",
"skip_sponsors": "Прапусціць спонсарскую рэкламу",
"skip_automatically": "Аўтаматычна",
"enable_sponsorblock": "Уключыць Sponsorblock",
"uses_api_from": "Выкарыстоўвае API ад "
},
"titles": {
"subscriptions": "Падпіскі",
"trending": "Папулярнае",
"login": "Уваход",
"preferences": "Налады",
"history": "Гісторыя",
"bookmarks": "Закладкі",
"channels": "Каналы",
"register": "Рэгістрацыя",
"livestreams": "Жывыя трансляцыі",
"feed": "Стужка",
"channel_groups": "Групы каналаў",
"account": "Ўліковы запіс",
"instance": "Інстанс",
"playlists": "Плэйлісты",
"player": "Прайгравальнік",
"dearrow": "DeArrow"
},
"player": {
"watch_on": "Прагляд на {0}",
"failed": "Памылка з кодам памылкі {0}, для атрымання дадатковай інфармацыі глядзіце журналы"
}
}

View file

@ -19,7 +19,7 @@
},
"actions": {
"most_recent": "Най-скорошен",
"unsubscribe": "Отписване - {count}",
"unsubscribe": "Отписване",
"uses_api_from": "Използва API от ",
"skip_sponsors": "Пропускане на спонсори",
"skip_preview": "Пропускане на преглед/обобщение",
@ -27,7 +27,7 @@
"min_segment_length": "Минимална дължина на сегмента (в секунди)",
"default_quality": "Качество по подразбиране",
"minimize_comments_default": "Минимизиране на коментарите по подразбиране",
"subscribe": "Абониране - {count}",
"subscribe": "Абониране",
"view_subscriptions": "Преглед на абонаменти",
"sort_by": "Сортиране по:",
"least_recent": "Най-малко скорошен",

View file

@ -12,8 +12,8 @@
"watch_on": "দেখুন {0}"
},
"actions": {
"subscribe": "সদস্যতা নিন - {count}",
"unsubscribe": "সদস্যতা পরিত্যাগ - {count}",
"subscribe": "সদস্যতা নিন",
"unsubscribe": "সদস্যতা পরিত্যাগ",
"view_subscriptions": "সদস্যতার তালিকা",
"sort_by": "ভিডিও গুলোর বিন্যাস:",
"most_recent": "সবচেয়ে সাম্প্রতিক",

View file

@ -11,10 +11,10 @@
"skip_interaction": "Preskoči podsjetnik interakcije (uz pretplatu)",
"show_comments": "Prikažite komentare",
"least_recent": "Najstariji",
"unsubscribe": "Otkažite pretplatu - {count}",
"unsubscribe": "Otkažite pretplatu",
"view_subscriptions": "Prikažite Pretplate",
"sort_by": "Poredajte po:",
"subscribe": "Pretplatite se - {count}",
"subscribe": "Pretplatite se",
"channel_name_asc": "Naziv kanala (A-Z)",
"back": "Nazad",
"create_playlist": "Stvorite popis snimaka",

View file

@ -64,8 +64,8 @@
"hide_replies": "Amaga les respostes",
"load_more_replies": "Carrega més respostes",
"view_subscriptions": "Mostra les subscripcions",
"subscribe": "Subscriu-me - {count}",
"unsubscribe": "Anul·la la subscripció - {count}",
"subscribe": "Subscriu-me",
"unsubscribe": "Anul·la la subscripció",
"sort_by": "Ordena per:",
"most_recent": "Més recents",
"least_recent": "Menys recents",
@ -95,7 +95,7 @@
"clone_playlist_success": "S'ha clonat correctament!",
"download_as_txt": "Baixa com a .txt",
"reset_preferences": "Restableix les preferències",
"restore_preferences": "Restaura les preferències",
"restore_preferences": "Importa les preferències",
"backup_preferences": "Exporta les preferències",
"confirm_reset_preferences": "Segur que voleu restablir les vostres preferències?",
"back_to_home": "Torna a l'inici",
@ -142,7 +142,11 @@
"auto_display_captions": "Mostra els subtítols automàticament",
"autoplay_next_countdown": "Compte enrere predefinit fins al pròxim vídeo (en segons)",
"generate_qrcode": "Genera un codi QR",
"playlist_name": "Nom de la llista de reproducció"
"playlist_name": "Nom de la llista de reproducció",
"add_to_group": "Afegeix al grup",
"instance_privacy_policy": "Política de privadesa",
"concurrent_prefetch_limit": "Límit de precàrrega de flux concurrent",
"instances_not_shown": "Les instàncies públiques que no es mostren aquí no es troben disponibles."
},
"comment": {
"pinned_by": "Fixat per {author}",
@ -157,7 +161,8 @@
"ssl_score": "Puntuació SSL",
"version": "Versió",
"up_to_date": "Actualitzada?",
"registered_users": "Usuaris registrats"
"registered_users": "Usuaris registrats",
"uptime_30d": "Temps d'activitat (30 d)"
},
"video": {
"watched": "Vist",
@ -214,6 +219,8 @@
"next_video_countdown": "Pròxim vídeo en {0}s",
"months": "{amount} mesos",
"weeks": "{amount} setmanes",
"days": "{amount} dies"
"days": "{amount} dies",
"login_note": "Inicieu la sessió amb un compte creat en aquesta instància.",
"register_note": "Registreu un compte en aquesta instància de Piped. Això us permetrà sincronitzar les vostres subscripcions i llistes de reproducció amb el vostre compte, perquè s'emmagatzemin al servidor. Podeu emprar totes les funcions sense un compte, però totes les dades es desaran a la memòria cau local del vostre navegador. Comproveu que no utilitzeu una adreça electrònica com a nom d'usuari, i trieu una contrasenya segura que no feu servir en cap altre lloc."
}
}

View file

@ -15,11 +15,13 @@
"channels": "Kanály",
"bookmarks": "Záložky",
"channel_groups": "Skupiny kanálů",
"dearrow": "DeArrow"
"dearrow": "DeArrow",
"albums": "Alba",
"custom_instances": "Vlastní instance"
},
"actions": {
"loop_this_video": "Přehrávat video ve smyčce",
"subscribe": "Odebírat - {count}",
"subscribe": "Odebírat",
"view_subscriptions": "Zobrazit odběry",
"sort_by": "Seřadit podle:",
"most_recent": "Nejnovější",
@ -68,7 +70,7 @@
"clear_history": "Smazat historii",
"hide_replies": "Skrýt odpovědi",
"load_more_replies": "Načíst další odpovědi",
"unsubscribe": "Zrušit odběr - {count}",
"unsubscribe": "Zrušit odběr",
"skip_sponsors": "Přeskočit sponzory",
"minimize_description": "Skrýt popis",
"skip_non_music": "Přeskočit hudbu: nehudební sekce",
@ -135,7 +137,7 @@
"cancel": "Zrušit",
"edit_playlist": "Upravit playlist",
"playlist_description": "Popis playlistu",
"okay": "Okay",
"okay": "Dobře",
"show_search_suggestions": "Zobrazit našeptávání ve vyhledávání",
"chapters_layout_mobile": "Rozložení kapitol na mobilu",
"enable_dearrow": "Povolit DeArrow",
@ -143,7 +145,18 @@
"generate_qrcode": "Vygenerovat QR kód",
"import_from_json_csv": "Importovat z JSON/CSV",
"download_frame": "Stáhnout snímek",
"instance_privacy_policy": "Ochrana údajů"
"instance_privacy_policy": "Ochrana údajů",
"add_to_group": "Přidat do skupiny",
"instances_not_shown": "Veřejné instance, které zde nejsou zobrazeny, momentálně nejsou dostupné.",
"concurrent_prefetch_limit": "Limit souběžných přednačtení streamů",
"customize": "Přizpůsobit",
"invalid_url": "Neplatná adresa URL!",
"add": "Přidat",
"delete_group_confirm": "Odstranit tuto skupinu?",
"creator_replied": "Odpověď autora",
"creator_liked": "Autorovi se líbilo",
"playback_speed": "Rychlost přehrávání",
"invalid_input": "Neplatné údaje"
},
"player": {
"watch_on": "Zobrazit na {0}",
@ -162,7 +175,9 @@
"ssl_score": "Stav SSL",
"registered_users": "Registrovaní uživatelé",
"up_to_date": "Aktuální?",
"version": "Verze"
"version": "Verze",
"uptime_30d": "Doba online (30d)",
"api_url": "Api URL"
},
"login": {
"username": "Uživatelské jméno",
@ -215,6 +230,8 @@
"hours": "{amount} hodin",
"days": "{amount} dnů",
"weeks": "{amount} týdnů",
"months": "{amount} měsíců"
"months": "{amount} měsíců",
"login_note": "Přihlaste se s účtem vytvořeným na této instanci.",
"register_note": "Zaregistrujte si účet na této instanci služby Piped. To vám umožní synchronizovat vaše odběry a seznamy skladeb s vaším účtem, takže budou uloženy na straně serveru. Všechny funkce můžete používat i bez účtu, ale všechna data budou uložena v místní mezipaměti prohlížeče. Ujistěte se, že jako uživatelské jméno NEPOUŽÍVÁTE e-mailovou adresu, a zvolte si bezpečné heslo, které nepoužíváte jinde."
}
}

View file

@ -31,8 +31,8 @@
"most_recent": "Am Neuesten",
"sort_by": "Sortieren nach:",
"view_subscriptions": "Abos anzeigen",
"unsubscribe": "Deabonnieren - {count}",
"subscribe": "Abonnieren - {count}",
"unsubscribe": "Deabonnieren",
"subscribe": "Abonnieren",
"enabled_codecs": "Aktivierte Codecs (Auswahl mehrerer Codecs möglich)",
"enable_lbry_proxy": "Proxy für LBRY einschalten",
"disable_lbry": "LBRY für Streaming deaktivieren",
@ -125,7 +125,12 @@
"generate_qrcode": "QR-Code generieren",
"import_from_json_csv": "Aus JSON/CSV importieren",
"download_frame": "Einzelbild (Frame) downloaden",
"instance_privacy_policy": "Datenschutzerklärung"
"instance_privacy_policy": "Datenschutzerklärung",
"add_to_group": "Zu Gruppe hinzufügen",
"instances_not_shown": "Öffentliche Instanzen, die hier nicht angezeigt werden, sind derzeit nicht verfügbar.",
"customize": "Anpassen",
"invalid_url": "Ungültige URL!",
"add": "Hinzufügen"
},
"player": {
"watch_on": "Auf {0} ansehen",
@ -147,7 +152,9 @@
"channels": "Kanäle",
"bookmarks": "Lesezeichen",
"channel_groups": "Kanalgruppen",
"dearrow": "DeArrow"
"dearrow": "DeArrow",
"albums": "Alben",
"custom_instances": "Benutzerdefinierte Instanzen"
},
"video": {
"sponsor_segments": "Sponsoren-Abschnitte",
@ -172,7 +179,9 @@
"instance_name": "Instanzname",
"registered_users": "Registrierte Benutzer",
"version": "Version",
"up_to_date": "Auf dem neuesten Stand?"
"up_to_date": "Auf dem neuesten Stand?",
"uptime_30d": "Uptime (30 Tage)",
"api_url": "API-URL"
},
"comment": {
"pinned_by": "Angeheftet von {author}",
@ -212,6 +221,8 @@
"weeks": "{amount} Woche(n)",
"months": "{amount} Monat(en)",
"hours": "{amount} Stunde(n)",
"days": "{amount} Tag(e)"
"days": "{amount} Tag(e)",
"login_note": "Melde dich mit einem Konto an, das du auf dieser Instanz erstellt hast.",
"register_note": "Erstelle ein Konto für diese Piped-Instanz. Dadurch kannst du deine Abos und Playlists mit deinem Konto synchronisieren, sie werden also serverseitig gespeichert. Du kannst all diese Funktionen auch ohne Konto nutzen, allerdings werden dann alle Daten nur im lokalen Speicher deines Browsers gespeichert. Bitte stelle sicher, dass du KEINE E-Mail-Adresse als Benutzernamen verwendest und ein sicheres Passwort wählst, welches du nicht bereits woanders nutzt."
}
}

View file

@ -4,7 +4,7 @@
"store_watch_history": "Αποθήκευση ιστορικού παρακολούθησης",
"default_homepage": "Προεπιλεγμένη αρχική σελίδα",
"country_selection": "Επιλογή χώρας",
"audio_only": "Ήχος μόνο",
"audio_only": "Μόνο ήχος",
"skip_non_music": "Παράλειψη μουσικής: Μη-μουσικό τμήμα",
"skip_self_promo": "Παράλειψη μη-χορηγούμενης/προσωπικής προώθησης",
"skip_preview": "Παράλειψη προεπισκόπησης/ανακεφαλαίωσης",
@ -31,8 +31,8 @@
"enable_sponsorblock": "Ενεργοποίηση Sponsorblock",
"back": "Επιστροφή",
"sort_by": "Ταξινόμηση κατά:",
"unsubscribe": "Απεγγραφή - {count}",
"subscribe": "Εγγραφή - {count}",
"unsubscribe": "Απεγγραφή",
"subscribe": "Εγγραφή",
"loop_this_video": "Επανάληψη αυτού του βίντεο",
"instance_selection": "Επιλογή διακομιστή",
"enabled_codecs": "Ενεργοποιημένοι κωδικοποητές (Πολλαπλοί)",
@ -44,7 +44,7 @@
"show_recommendations": "Εμφάνιση συστάσεις",
"donations": "Δωρεές",
"auto_play_next_video": "Αυτόματη αναπαραγωγή επόμενου βίντεο",
"import_from_json": "Εισαγωγή από JSON/CSV",
"import_from_json": "Εισαγωγή από JSON",
"export_to_json": "Εξαγωγή σε JSON",
"no": "Όχι",
"yes": "Ναι",
@ -65,20 +65,89 @@
"add_to_playlist": "Προσθήκη στη λίστα αναπαραγωγής",
"clear_history": "Καθαρισμός ιστορικού",
"delete_playlist_video_confirm": "Είστε σίγουρος οτι θέλετε να αφαιρέσετε αυτό το βίντεο απο την λίστα αναπαραγωγής;",
"delete_playlist_confirm": "Είστε σίγουρος οτι θέλετε να διαγράψετε αυτή την λίστα αναπαραγωγής;"
"delete_playlist_confirm": "Διαγραφή λίστας αναπαραγωγής;",
"okay": "Εντάξει",
"edit_playlist": "Επεξεργασία λίστας αναπαραγωγής",
"group_name": "Όνομα γκρουπ",
"invalidate_session": "Αποσύνδεση από όλες τις συσκευές",
"playlist_bookmarked": "Σώθηκε ως σελιδοδείκτης",
"add_to_group": "Προσθήκη στο γκρουπ",
"confirm_reset_preferences": "Είσαι σίγουρος ότι θες να επαναφέρεις τις προτιμήσεις σου;",
"reply_count": "{count} απαντήσεις",
"restore_preferences": "Εποκατάσταση προτιμήσεων",
"piped_link": "Σύνδεσμος Piped",
"skip_button_only": "Εμφάνισε κουμπί παράλειψης",
"minimize_comments_default": "Ελαχιστοποίηση σχολίων από προεπιλογή",
"import_from_json_csv": "Εισαγωγή από JSON/CSV",
"cancel": "Ακύρωση",
"playlist_description": "Περιγραφή λίστας αναπαραγωγής",
"download_as_txt": "Κατέβασμα σε .txt",
"source_code": "Πηγαίος κώδικας",
"copy_link": "Αντιγραφή συνδέσμου",
"dismiss": "Παράλειψη",
"hide_watched": "Απόκρυψη βίντεο που έχουν προβληθεί από το feed",
"delete_account": "Διαγραφή λογαριασμού",
"backup_preferences": "Αντίγραφο προτιμήσεων",
"instance_donations": "Δωρεά σε διακομιστή",
"with_playlist": "Κοινοποίηση με λίστα αναπαραγωγής",
"store_search_history": "Αποθήκευση ιστορικού αναζήτησης",
"share": "Κοινοποίηση",
"delete_automatically": "Αυτόματη διαγραφή μετά από",
"show_less": "Εμφάνιση λιγότερων",
"logout": "Αποσύνδεση από τη συγκεκριμένη συσκευή",
"reset_preferences": "Επαναφορά προτιμήσεων",
"download_frame": "Λήψη καρέ",
"create_group": "Δημιουργία γκρουπ",
"show_chapters": "Κεφάλαια",
"back_to_home": "Πίσω στην αρχική",
"skip_segment": "Παράλειψη τμήματος αναπαραγωγής",
"show_search_suggestions": "Εμφάνιση προτάσεων αναζήτησης",
"clone_playlist_success": "Αντιγράφηκε επιτυχώς!",
"instance_auth_selection": "Διακομιστής επιβεβαίωσης στοιχείων",
"documentation": "Έγγραφα/Οδηγοί",
"different_auth_instance": "Χρήση διαφορετικού διακομιστή για επιβεβαίωση στοιχείων",
"minimize_comments": "Ελαχιστοποίηση σχολίων",
"skip_automatically": "Αυτόματα",
"status_page": "Κατάσταση",
"show_markers": "Εμφάνισε τα στιγμιότυπα αναπαραγωγής",
"show_watch_on_youtube": "Εμφάνισε κουμπί \"Αναπαραγωγή στο YouTube\"",
"autoplay_next_countdown": "Προεπιλογή χρόνου αναμονής μέχρι το επόμενο βίντεο (σε δευτερόλεπτα)",
"generate_qrcode": "Δημιουργία QR Code",
"playlist_name": "Όνομα λίστας αναπαραγωγής",
"minimize_chapters_default": "Ελαχιστοποίηση τμημάτων αναπαραγωγής από προεπιλογή",
"instance_privacy_policy": "Πολιτική απορρήτου",
"minimize_recommendations_default": "Ελαχιστοποίηση προτάσεων από προεπιλογή",
"instances_not_shown": "Οι δημόσιοι πάροχοι σύνδεσης που δεν εμφανίζονται εδώ, ελιναι προσωρινά μη διαθέσιμοι.",
"no_valid_playlists": "Το αρχείο δεν περιέχει έγκυρες λίστες αναπαραγωγής!",
"min_segment_length": "Ελάχιστη διάρκεια τμήματος αναπαραγωγής (σε δευτερόλεπτα)",
"bookmark_playlist": "Σελιδοδείκτης",
"clone_playlist": "Αντιγραφή λίστας αναπαραγωγής",
"enable_dearrow": "Ενεργοποίηση De Arrow",
"auto_display_captions": "Αυτόματη εμφάνιση λεζαντών",
"with_timecode": "Κοινοποίηση με συγκεκριμένο σημείο αναπαραγωγής",
"time_code": "Χρονικό σημείο (σε δευτερόλεπτα)"
},
"titles": {
"feed": "Τροφοδοσία",
"feed": "Νεότερα",
"history": "Ιστορικό",
"preferences": "Ρυθμίσεις",
"register": "Εγγραφή",
"login": "Σύνδεση",
"trending": "Τάσεις",
"subscriptions": "Συνδρομές",
"playlists": "Λίστες αναπαραγωγής"
"playlists": "Λίστες αναπαραγωγής",
"livestreams": "Ζωντανές Ροές",
"channel_groups": "Γκρουπ Καναλιών",
"account": "Λογαριασμός",
"instance": "Διακομιστής",
"bookmarks": "Σελιδοδείκτες",
"channels": "Κανάλια",
"player": "Πρόγραμμα αναπαραγωγής",
"dearrow": "De Arrow"
},
"player": {
"watch_on": "Παρακολούθηση στο {0}"
"watch_on": "Παρακολούθηση στο {0}",
"failed": "Κωδικός σφάλματος {0}, δες τα logs για περισσότερες πληροφορίες"
},
"video": {
"watched": "Προβλήθηκε",
@ -87,7 +156,14 @@
"videos": "Βίντεο",
"live": "{0} Ζωντανή μετάδοση",
"ratings_disabled": "Οι αξιολογήσεις είναι απενεργοποιημένες",
"chapters": "Κεφάλαια"
"chapters": "Κεφάλαια",
"all": "Όλα",
"shorts": "Σύντομα βίντεο",
"visibility": "Εμφάνιση",
"license": "Άδεια",
"category": "Κατηγορία",
"chapters_vertical": "Κάθετα",
"chapters_horizontal": "Οριζόντια"
},
"preferences": {
"ssl_score": "SSL σκόρ",
@ -99,11 +175,16 @@
"up_to_date": "Ενημερωμένο;"
},
"comment": {
"pinned_by": "Καρφιτσώθηκε από τον {author}"
"pinned_by": "Καρφιτσώθηκε από τον {author}",
"loading": "Φόρτωση σχολίων...",
"user_disabled": "Τα σχόλια έχουν απενεργοποιηθεί στις ρυθμίσεις.",
"disabled": "Τα σχόλια έχουν απενεργοποιηθεί από το διαχειριστή του καναλιού."
},
"login": {
"password": "Κωδικός πρόσβασης",
"username": "Όνομα χρήστη"
"username": "Όνομα χρήστη",
"password_confirm": "Επιβεβαίωση κωδικού",
"passwords_incorrect": "Οι κωδικοί δεν ταιριάζουν!"
},
"search": {
"did_you_mean": "Μήπως εννοείτε: {0};",
@ -114,6 +195,25 @@
"music_songs": "YT Music: Τραγούδια",
"music_videos": "YT Music: Βίντεο",
"channels": "YouTube: Κανάλια",
"music_playlists": "YT Music: Λίστες αναπαραγωγής"
"music_playlists": "YT Music: Λίστες αναπαραγωγής",
"music_artists": "YT Music: Καλλιτέχνες"
},
"info": {
"hours": "{amount} ώρα(ες)",
"next_video_countdown": "Αναπαραγωγή επόμενου βίντεο σε {0} δευτερόλεπτα",
"preferences_note": "Σημείωση: Οι προτιμήσεις σας έχουν αποθηκευτεί τοπικά στη μνήμη του browser. Διαγράφοντας τα δεδομένα του browser, σβήνετε και τις προτιμήσεις αυτές.",
"local_storage": "Η ενέργεια αυτή χρειάζεται τοπικό χώρο αποθήκευσης, έχετε ενεργοποιημένα τα cookies;",
"cannot_copy": "Αδυναμία αντιγραφής!",
"login_note": "Συνδεθείτε με λογαριασμό που έχει δημιουργθεί σε αυτό το διακομιστή.",
"months": "{amount} μήνα(ες)",
"page_not_found": "Η σελίδα δε βρέθηκε",
"weeks": "{amount} εβδομάδα(ες)",
"register_note": "Καταχωρήστε ένα λογαριασμό για το συγκεκριμένο Piped διακομιστή. Αυτό θα επιτρέψει να συγχρονίσετε τις συνδρομές και τις λίστες αναπαραγωγής σας με το λογαριασμό, ώστε να αποθηκευτούν στο server. Μπορείτε να χρησιμοποιήσετε όλα τα features χωρίς λογαριασμό, όμως τα δεδομένα θα αποθηκευτούν στην προσωρινή μνήμη του browser σας. Παρακαλώ βεβαιωθείτε ότι ΔΕΝ χρησιμοποιείτε email ως όνομα χρήστη και επιλέξτε έναν ασφαλή κωδικό τον οποίο δε χρησιμοποιείτε αλλού.",
"register_no_email_note": "Η χρήση e-mail για όνομα χρήστη δε συνίσταται. Θέλετε να προχωρήσετε;",
"days": "{amount} μέρα(ες)",
"copied": "Αντιγράφηκε!"
},
"subscriptions": {
"subscribed_channels_count": "Συνδρομή σε: {0}"
}
}

View file

@ -13,17 +13,19 @@
"player": "Player",
"livestreams": "Livestreams",
"channels": "Channels",
"albums": "Albums",
"bookmarks": "Bookmarks",
"channel_groups": "Channel groups",
"dearrow": "DeArrow"
"dearrow": "DeArrow",
"custom_instances": "Custom instances"
},
"player": {
"watch_on": "View on {0}",
"failed": "Failed with error code {0}, see logs for more info"
},
"actions": {
"subscribe": "Subscribe - {count}",
"unsubscribe": "Unsubscribe - {count}",
"subscribe": "Subscribe",
"unsubscribe": "Unsubscribe",
"view_subscriptions": "View Subscriptions",
"sort_by": "Sort by:",
"most_recent": "Most Recent",
@ -32,6 +34,7 @@
"channel_name_desc": "Channel Name (Z-A)",
"back": "Back",
"uses_api_from": "Uses the API from ",
"instances_not_shown": "Public instances that are not shown here are currently unavailable.",
"enable_sponsorblock": "Enable Sponsorblock",
"skip_button_only": "Show skip button",
"skip_automatically": "Automatically",
@ -98,6 +101,7 @@
"delete_playlist": "Delete",
"select_playlist": "Select a Playlist",
"delete_playlist_confirm": "Delete this playlist?",
"delete_group_confirm": "Delete this group?",
"please_select_playlist": "Please select a playlist",
"delete_account": "Delete Account",
"logout": "Logout from this device",
@ -147,7 +151,16 @@
"show_search_suggestions": "Show search suggestions",
"delete_automatically": "Delete automatically after",
"generate_qrcode": "Generate QR Code",
"download_frame": "Download frame"
"download_frame": "Download frame",
"add_to_group": "Add to group",
"concurrent_prefetch_limit": "Concurrent Stream Prefetch Limit",
"customize": "Customize",
"invalid_url": "Invalid URL!",
"add": "Add",
"creator_replied": "Creator replied",
"creator_liked": "Creator liked",
"playback_speed": "Playback speed",
"invalid_input": "Invalid input"
},
"comment": {
"pinned_by": "Pinned by {author}",
@ -162,7 +175,9 @@
"registered_users": "Registered Users",
"version": "Version",
"up_to_date": "Up to date?",
"ssl_score": "SSL Score"
"ssl_score": "SSL Score",
"uptime_30d": "Uptime (30d)",
"api_url": "Api URL"
},
"login": {
"username": "Username",
@ -212,6 +227,8 @@
"hours": "{amount} hour(s)",
"days": "{amount} day(s)",
"weeks": "{amount} week(s)",
"months": "{amount} month(s)"
"months": "{amount} month(s)",
"register_note": "Register an account for this Piped instance. This will allow you to sync your subscriptions and playlists with your account, so they're stored on the server side. You can use all features without an account, but all data will be stored in your browser's local cache. Please make sure you do NOT use an email address as your username and choose a secure password that you do not use elsewhere.",
"login_note": "Log in with an account created on this instance."
}
}

View file

@ -10,7 +10,7 @@
"playlists": "Ludlistoj",
"account": "Konto",
"player": "Ludilo",
"instance": "Nodo",
"instance": "Retejo",
"channels": "Kanaloj",
"livestreams": "Tujelsendoj",
"bookmarks": "Legosignoj",
@ -22,8 +22,8 @@
"failed": "Fiaskis kun erarkodo {0}, vidu protokolojn por pli da informo"
},
"actions": {
"subscribe": "Aboni - {count}",
"unsubscribe": "Malaboni - {count}",
"subscribe": "Aboni",
"unsubscribe": "Malaboni",
"view_subscriptions": "Vidi Abonojn",
"sort_by": "Ordigi laŭ:",
"most_recent": "Plej Freŝaj",
@ -81,11 +81,11 @@
"enable_lbry_proxy": "Ebligi Prokurilon por LBRY",
"import_from_json": "Importi el JSON",
"show_description": "Montri Priskribon",
"instances_list": "Listo de Nodoj",
"instances_list": "Listo de Piped-retejoj",
"auto_play_next_video": "Aŭtomate Ludi sekvan Videon",
"show_recommendations": "Montri Rekomendojn",
"reset_preferences": "Restarigi agordojn",
"instance_selection": "Nodo",
"instance_selection": "Retejo",
"view_ssl_score": "Vidu SSL-Poentaron",
"backup_preferences": "Savkopii agordojn",
"disable_lbry": "Malebligi LBRY-n por Elsendfluo",
@ -93,11 +93,11 @@
"store_search_history": "Konservi Ŝerĉhistorion",
"hide_watched": "Kaŝi viditajn videojn en la fluo",
"minimize_recommendations": "Plejetigi Rekomendojn",
"instance_auth_selection": "Aŭtentokontrola nodo",
"instance_auth_selection": "Aŭtentokontrola Piped-retejo",
"restore_preferences": "Restarigi agordojn",
"status_page": "Stato",
"please_select_playlist": "Bonvolu elekti ludliston",
"different_auth_instance": "Uzi alian nodon por aŭtentokontrolo",
"different_auth_instance": "Uzi alian Piped-retejon por aŭtentokontrolo",
"back_to_home": "Ree hejmen",
"time_code": "Tempkodo (en sekundoj)",
"skip_non_music": "Preterpasi Muzikon: Nemuzika Sekcio",
@ -147,7 +147,8 @@
"generate_qrcode": "Generi QR-kodon",
"import_from_json_csv": "Importi el JSON/CSV",
"download_frame": "Elŝuti bildon",
"instance_privacy_policy": "Privateca politiko"
"instance_privacy_policy": "Privateca politiko",
"add_to_group": "Aldoni al grupo"
},
"video": {
"chapters": "Sekcioj",
@ -188,7 +189,9 @@
"hours": "{amount} horo(j)",
"days": "{amount} tago(j)",
"weeks": "{amount} semajno(j)",
"months": "{amount} monato(j)"
"months": "{amount} monato(j)",
"login_note": "Ensaluti per konto kreita en ĉi tiu retejo.",
"register_note": "Registri konton por ĉi tiu Piped-retejo. Tio ebligos al vi sinkronigi viajn abonojn kaj ludlistojn kun via konto, do ili estos konservitaj en la servilo. Vi ankaŭ povas uzi ĉiujn funkciojn sen konto, sed ĉiuj datenoj estos konservitaj en la loka kaŝmemoro de via retumilo. Bonvolu elekti sekuran pasvorton, kiun vi ne uzas aliloke, kaj NE uzi retadreson kiel uzantnomon."
},
"login": {
"username": "Uzantnomo",

View file

@ -22,7 +22,9 @@
"instance_name": "Nombre de la instancia",
"version": "Versión",
"up_to_date": "¿Actualizado?",
"registered_users": "Usuarios Registrados"
"registered_users": "Usuarios Registrados",
"uptime_30d": "Tiempo de actividad (30d)",
"api_url": "URL de la API"
},
"comment": {
"pinned_by": "Fijado por {author}",
@ -76,8 +78,8 @@
"most_recent": "Lo más reciente",
"sort_by": "Ordenar por:",
"view_subscriptions": "Ver suscripciones",
"unsubscribe": "Anular suscripción - {count}",
"subscribe": "Suscribirme - {count}",
"unsubscribe": "Anular suscripción",
"subscribe": "Suscribirme",
"loading": "Cargando…",
"filter": "Filtrar",
"search": "Buscar (Ctrl+K)",
@ -156,7 +158,18 @@
"generate_qrcode": "Generar código QR",
"import_from_json_csv": "Importar desde JSON/CSV",
"download_frame": "Descargar fotograma",
"instance_privacy_policy": "Política de privacidad"
"instance_privacy_policy": "Política de privacidad",
"add_to_group": "Añadir a grupo",
"instances_not_shown": "Las instancias públicas que no se muestran aquí no están disponibles actualmente.",
"concurrent_prefetch_limit": "Límite de captación previa de transmisiones simultáneas",
"customize": "Personalizar",
"invalid_url": "¡URL no válida!",
"add": "Añadir",
"delete_group_confirm": "¿Eliminar este grupo?",
"creator_liked": "Al autor le gustó",
"creator_replied": "El autor respondió",
"playback_speed": "Velocidad de reproducción",
"invalid_input": "Entrada no válida"
},
"titles": {
"feed": "Contenido",
@ -174,7 +187,9 @@
"channels": "Canales",
"bookmarks": "Marcadores",
"channel_groups": "Grupos de canales",
"dearrow": "DeArrow"
"dearrow": "DeArrow",
"albums": "Álbumes",
"custom_instances": "Instancias personalizadas"
},
"player": {
"watch_on": "Ver en {0}",
@ -212,6 +227,8 @@
"hours": "{amount} hora(s)",
"days": "{amount} día(s)",
"weeks": "{amount} semana(s)",
"months": "{amount} mes(es)"
"months": "{amount} mes(es)",
"login_note": "Inicia sesión con una cuenta creada en esta instancia.",
"register_note": "Registra una cuenta para esta instancia de Piped. Esto te permitirá sincronizar tus suscripciones y las listas de reproducción con tu cuenta, para que se almacenen en el servidor. Puedes utilizar todas las funciones sin una cuenta, pero todos los datos se almacenarán en la caché local de tu navegador. Asegúrate de NO utilizar una dirección de correo electrónico como nombre de usuario y elige una contraseña segura que no utilices en ningún otro sitio."
}
}

View file

@ -7,87 +7,169 @@
"register": "Registreeri",
"subscriptions": "Tellimused",
"history": "Ajalugu",
"playlists": "Esitusloendid"
"playlists": "Esitusloendid",
"account": "Kasutajakonto",
"player": "Meediamängija",
"instance": "Vaheserver",
"bookmarks": "Järjehoidjad",
"dearrow": "DeArrow",
"livestreams": "Otseetrid",
"channels": "Kanalid",
"channel_groups": "Kanalite grupid",
"albums": "Albumid",
"custom_instances": "Kohandatud vaheserverid"
},
"player": {
"watch_on": "Vaata saidil {0}"
"watch_on": "Vaata {0} saidis",
"failed": "Tegevus ei õnnestunud, veakood {0}; lisateavet leiad logidest"
},
"actions": {
"subscribe": "Telli - {count}",
"unsubscribe": "Loobuda tellitud - {count}",
"subscribe": "Telli",
"unsubscribe": "Lõpeta tellimus",
"view_subscriptions": "Vaata tellimusi",
"sort_by": "Sorteerimine:",
"most_recent": "Viimane",
"least_recent": "Kõige vähem hiljutine",
"least_recent": "Kõige vanem",
"channel_name_asc": "Kanali nimi (A-Ü)",
"channel_name_desc": "Kanali nimi (Ü-A)",
"back": "Tagasi",
"uses_api_from": "Kasutab API-d ",
"enable_sponsorblock": "Sponsorblock lubamine",
"skip_sponsors": "Sponsorite vahelejätmine",
"skip_intro": "Vaheaja vahelejätmine/Intro animatsioon",
"skip_outro": "Jäta lõppkaardid/krediidid vahele",
"skip_preview": "Jäta eelvaade/kokkuvõte vahele",
"uses_api_from": "Kasutusel on API: ",
"enable_sponsorblock": "Luba Sponsorblock",
"skip_sponsors": "Jäta sponsorid vahele",
"skip_intro": "Jäta vahe- ja intriklipid vahele",
"skip_outro": "Jäta lõppkaardid ja tunustused vahele",
"skip_preview": "Jäta eelvaade või kokkuvõte vahele",
"skip_non_music": "Muusika vahelejätmine: Mitte-muusika sektsioon",
"theme": "Teema",
"default_quality": "Standardkvaliteet",
"country_selection": "Riigi valimine",
"country_selection": "Riik",
"default_homepage": "Vaikimisi koduleht",
"language_selection": "Kelle valik",
"instances_list": "Intsidentide nimekiri",
"language_selection": "Keel",
"instances_list": "Vaheserverite loend",
"show_more": "Näita rohkem",
"yes": "Jah",
"no": "Ei",
"export_to_json": "Eksportida JSON-vormingusse",
"import_from_json": "Importimine JSON/CSVist",
"loop_this_video": "Selle video pidev taasesitus",
"donations": "Annetused",
"export_to_json": "Ekspordi JSON-vormingusse",
"import_from_json": "Impordi JSON'ist",
"loop_this_video": "Esita seda videot lõputult",
"donations": "Toeta arendust",
"minimize_description": "Minimeeri kirjeldus",
"minimize_recommendations": "Soovituste minimeerimine",
"disable_lbry": "LBRY väljalülitamine voogedastuse jaoks",
"search": "Otsige",
"filter": "Filtreeri järgi",
"loading": "Laadimine...",
"clear_history": "Tühjendage ajalugu",
"minimize_recommendations": "Minimeeri soovitused",
"disable_lbry": "Lülita LBRY voogedastuse puhul välja",
"search": "Otsi (Ctrl+K)",
"filter": "Filtreeri",
"loading": "Laadime...",
"clear_history": "Tühjenda ajalugu",
"hide_replies": "Peida vastused",
"load_more_replies": "Lae alla rohkem vastuseid",
"load_more_replies": "Laadi alla rohkem vastuseid",
"add_to_playlist": "Lisa esitusloendisse",
"create_playlist": "Loo esitusloend",
"delete_playlist": "Kustuta esitusloend",
"skip_highlight": "Jäta tipphetk vahele",
"skip_interaction": "Jäta interaktsiooni meeldetuletus vahele (Telli)",
"light": "Valgus",
"skip_interaction": "Jäta interaktsiooni meeldetuletus vahele (Tellimine)",
"light": "Hele",
"auto": "Automaatne",
"skip_self_promo": "Jäta tasustamata/enesereklaami vahele",
"skip_filler_tangent": "Jäta filler'i vahelejätmine",
"skip_self_promo": "Jäta tasustamata või enesereklaam vahele",
"skip_filler_tangent": "Jäta filler'i vahele",
"dark": "Tume",
"autoplay_video": "Mängi videot automaatselt",
"buffering_goal": "Puhverdamise eesmärk (sekundites)",
"buffering_goal": "Puhverdamise kestus (sekundites)",
"show_comments": "Näita kommentaare",
"audio_only": "Ainult heli",
"store_watch_history": "Salvesta oma vaatamise ajalugu",
"instance_selection": "Instantsi valik",
"instance_selection": "Vaheserver",
"show_recommendations": "Näita soovitusi",
"minimize_description_default": "Vähenda kirjeldust vaikimisi",
"minimize_description_default": "Vaikimisi minimeeri kirjeldus",
"enabled_codecs": "Kasutatavad koodekid (mitu)",
"auto_play_next_video": "Järgmise video automaatne esitamine",
"view_ssl_score": "Näita SSL skoore",
"enable_lbry_proxy": "LBRY proxy-serveri aktiveerimine",
"auto_play_next_video": "Esita järgmist videot automaatselt",
"view_ssl_score": "Vaata SSL-punkte",
"enable_lbry_proxy": "Kasuta LBRY puhul puhverserverit",
"show_description": "Näita kirjeldust",
"delete_playlist_confirm": "Kas olete kindel, et soovite selle esitusloendi kustutada?",
"delete_playlist_confirm": "Kas soovid selle esitusloendi kustutada?",
"remove_from_playlist": "Eemalda esitusloendist",
"delete_playlist_video_confirm": "Kas olete kindel, et soovite selle video sellest esitusloendist eemaldada?",
"select_playlist": "Valige esitusloend",
"please_select_playlist": "Valige esitusloend"
"delete_playlist_video_confirm": "Kas soovid selle video sellest esitusloendist eemaldada?",
"select_playlist": "Vali esitusloend",
"please_select_playlist": "Palun vali esitusloend",
"playlist_name": "Esitusloendi nimi",
"with_timecode": "Jaga koos ajahetkega",
"show_chapters": "Peatükid",
"status_page": "Olek",
"instance_donations": "Toeta vaheserverite haldajaid",
"with_playlist": "Jaga koos esitusloendiga",
"playlist_bookmarked": "Lisatud järjehoidjaks",
"dismiss": "Katkesta",
"create_group": "Loo grupp",
"okay": "Sobib",
"show_search_suggestions": "Näita otsingusoovitusi",
"instance_auth_selection": "Vaheserver autentimiseks",
"store_search_history": "Salvesta otsinguajalugu",
"hide_watched": "Peida vaadatud videod meediavoost",
"logout": "Logi sellest seadmest välja",
"show_less": "Näita vähem",
"delete_automatically": "Kustuta automaatselt peale",
"minimize_chapters_default": "Vaikimisi kuva peatükid minimeerituna",
"reset_preferences": "Lähtesta eelistused",
"concurrent_prefetch_limit": "Samaaegse meediavoo eellaadimise piir",
"cancel": "Katkesta",
"generate_qrcode": "Loo QR-kood",
"import_from_json_csv": "Impordi JSON- või CSV-failist",
"confirm_reset_preferences": "Kas sa oled kindel, et soovid eelistused lähtestada?",
"backup_preferences": "Varunduse eelistused",
"back_to_home": "Tagasi avalehele",
"playlist_description": "Esitusloendi kirjeldus",
"share": "Jaga",
"source_code": "Lähtekood",
"no_valid_playlists": "Selles failis ei leidu korrektseid esitusloendeid!",
"group_name": "Grupi nimi",
"minimize_comments": "Minimeeri kommentaarid",
"auto_display_captions": "Kuva tiitrid automaatselt",
"delete_account": "Kustuta konto",
"invalidate_session": "Logi kõikidest seadmetest välja",
"clone_playlist_success": "Koopia tegemine õnnestus!",
"instances_not_shown": "Kui avalik vaheserver pole siin kuvatud, siis pole ta hetkel kasutatav.",
"skip_button_only": "Näita nuppu „Jäta vahele“",
"skip_automatically": "Automatselt",
"show_markers": "Näita meediamängijas markereid",
"min_segment_length": "Väikseim segmendi pikkus (sekundites)",
"skip_segment": "Jäta segment vahele",
"enable_dearrow": "Pisipiltide kuvamiseks kasuta DeArrow teenust",
"autoplay_next_countdown": "Vaikimisi viivitus järgmise video esitamiseni (sekundites)",
"minimize_comments_default": "Vaikimisi minimeeri kommentaarid",
"minimize_recommendations_default": "Vaikimisi kuva soovitused minimeerituna",
"chapters_layout_mobile": "Peatükkide paigutus telefonivaates",
"show_watch_on_youtube": "Näita „Vaata YouTube's“ nuppu",
"different_auth_instance": "Kasuta autentimiseks teist vaheserverit",
"clone_playlist": "Tee esitusloendist koopia",
"download_as_txt": "Laadi alla txt-failina",
"restore_preferences": "Taasta eelistused",
"edit_playlist": "Muuda esitusloendit",
"follow_link": "Ava link",
"piped_link": "Link Piped'i saiti",
"copy_link": "Kopeeri link",
"time_code": "Ajahetk esituses (sekundites)",
"documentation": "Dokumentatsioon",
"reply_count": "{count} vastust",
"bookmark_playlist": "Järjehoidja",
"download_frame": "Laadi alla kaader",
"add_to_group": "Lisa gruppi",
"instance_privacy_policy": "Privaatsuspoliitika",
"customize": "Kohanda",
"invalid_url": "Vigane URL!",
"add": "Lisa",
"delete_group_confirm": "Kas kustutame selle grupi?",
"creator_replied": "Autor vastas",
"creator_liked": "Autorile meeldis see"
},
"preferences": {
"has_cdn": "Kas on CDN?",
"has_cdn": "CDN'i olek?",
"ssl_score": "SSL-punktid",
"registered_users": "Registreeritud kasutajad",
"up_to_date": "Ajakohastatud?",
"instance_name": "Instantsi nimi",
"instance_locations": "Instantsi asukoht",
"version": "Versioon"
"up_to_date": "Kõik on ajakohane?",
"instance_name": "Vaheserveri nimi",
"instance_locations": "Vaheserveri asukohad",
"version": "Versioon",
"uptime_30d": "Tõrgeteta tööaeg (30p)",
"api_url": "API URL"
},
"video": {
"videos": "Videod",
@ -96,7 +178,14 @@
"sponsor_segments": "Sponsorite segmendid",
"chapters": "Peatükid",
"live": "{0} Otseülekanne",
"ratings_disabled": "Hinnangud välja lülitatud"
"ratings_disabled": "Hinnangud välja lülitatud",
"chapters_vertical": "Püstloodis",
"chapters_horizontal": "Rõhtloodis",
"shorts": "Lühivideod",
"all": "Kõik",
"category": "Kategooria",
"license": "Litsents",
"visibility": "Nähtavus"
},
"search": {
"did_you_mean": "Kas sa mõtlesid: {0}?",
@ -107,13 +196,37 @@
"music_songs": "YT Music: Laulud",
"music_videos": "YT Music: Videod",
"music_albums": "YT Music: Albumid",
"music_playlists": "YT Music: Esitusloendid"
"music_playlists": "YT Music: Esitusloendid",
"music_artists": "YT Music: Esitajad"
},
"login": {
"username": "Kasutajanimi",
"password": "Parool"
"password": "Parool",
"password_confirm": "Kinnita salasõna õigsust",
"passwords_incorrect": "Salasõnad ei klapi omavahel!"
},
"comment": {
"pinned_by": "Kinnitanud {author}"
"pinned_by": "Esile tõstnud: {author}",
"loading": "Laadime kommentaare...",
"user_disabled": "Kommentaarid on seadistusest välja lülitatud.",
"disabled": "Video üleslaadija ei luba kommentaare."
},
"subscriptions": {
"subscribed_channels_count": "Tellitud kanaleid: {0}"
},
"info": {
"page_not_found": "Veebilehte ei leidu",
"copied": "Kopeeritud!",
"cannot_copy": "Kopeerimine ei õnnestu!",
"local_storage": "Selle tegevuse jaoks on oluline brauseri localStorage kasutamine. Kas küpsiste salvestamine on lubatud?",
"next_video_countdown": "Järgmise video esitamiseni {0}s",
"hours": "{amount} tund(i)",
"days": "{amount} päev(a)",
"weeks": "{amount} nädal(at)",
"months": "{amount} kuu(d)",
"login_note": "Logi sisse kontoga, mis on loodud selles vaheserveris.",
"register_note": "Registreeri konto selles Piped'i vaheserveris. Nii tehes on sul võimalik sünkroniseerida oma tellimused ja esitusloendid oma kontole ja sellega neid serveris salvestada. Vastasel juhul saad sa kasutada selle veebisaidi terviklikku funktsionaalsust, kuid andmeid hoitakse vaid selle veebibrauseri andmehoidlas. Konto loomisel palun ära kasuta oma e-postiaadressi kasutajanimena ning loo turvaline salasõna, mida sa mujal ei kasuta.",
"preferences_note": "Märkus: eelistused on salvestatud sinu veebibrauseri kohalikus andmekogus. Baruseris salvestatud andmete kustutamisel kõik seadistused lähtestuvad.",
"register_no_email_note": "Meie ei soovita kasutajanimeks e-posti aadressi. Kas ikkagi jätkame?"
}
}

View file

@ -60,8 +60,8 @@
"most_recent": "Berriena",
"sort_by": "Ordenatu honen arabera:",
"view_subscriptions": "Harpidetzak ikusi",
"unsubscribe": "Kendu harpidetza - {count}",
"subscribe": "Harpidetu - {count}",
"unsubscribe": "Kendu harpidetza",
"subscribe": "Harpidetu",
"loading": "Kargatzen...",
"filter": "Iragazi",
"search": "Bilatu",

View file

@ -24,12 +24,12 @@
"most_recent": "تازه‌ترین‌ها",
"sort_by": "مرتب سازی بر اساس:",
"view_subscriptions": "مشاهده سابسکرایب ها",
"unsubscribe": "لغو سابسکرایب - {count}",
"subscribe": "سابسکرایب - {count}",
"unsubscribe": "لغو سابسکرایب",
"subscribe": "سابسکرایب",
"minimize_recommendations": "بستن توصیه ها",
"show_recommendations": "نمایش توصیه ها",
"uses_api_from": "با استفاده از APIای از ",
"instance_selection": "انتخاب نمونه",
"instance_selection": "انتخاب سرویس دهنده",
"show_more": "نمایش بیشتر",
"yes": "بله",
"no": "خیر",
@ -42,7 +42,7 @@
"skip_interaction": "رد کردن یاداوری سابسکرایب",
"skip_highlight": "رد کردن نکات برجسته",
"skip_filler_tangent": "رد کردن چرندیات نامربوط",
"import_from_json": "وارد کردن از JSON/CSV",
"import_from_json": "وارد کردن از JSON",
"export_to_json": "دادن خروجی با فرمت JSON",
"show_description": "نمایش توضیحات ویدئو",
"donations": "کمک های مالی برای توسعه",
@ -68,15 +68,67 @@
"logout": "خروج از این دستگاه",
"delete_playlist_video_confirm": "ویدیو از لیست پخش حذف شود؟",
"autoplay_next_countdown": "پیش‌فرض شمارش‌معکوس پخش ویدیوی بعدی ( به ثانیه )",
"please_select_playlist": "انتخاب لیست پخش",
"please_select_playlist": "لطفا فهرست پخش را انتخاب کنید",
"minimize_comments_default": "کوچک کردن کامنت‌ها به صورت پیش فرض",
"minimize_comments": "کوچک کردن کامنت (نظرات)",
"remove_from_playlist": "حذف از لیست پخش",
"skip_button_only": "دکمه‌ی گذر را نشان بده",
"skip_automatically": "خودکار",
"skip_segment": "گذر از بخش",
"minimize_recommendations_default": "به طور پیش فرض پیشنهادها را حداقل کنید.",
"min_segment_length": "حداقل طول بخش (به ثانیه)"
"minimize_recommendations_default": "به طور پیش فرض پیشنهادها را حداقل کنید",
"min_segment_length": "حداقل طول بخش (به ثانیه)",
"okay": "تایید",
"edit_playlist": "ویرایش فهرست‌پخش",
"group_name": "نام گروه",
"invalidate_session": "خروج از همهٔ دستگاه‌ها",
"add_to_group": "افزودن به گروه",
"confirm_reset_preferences": "از بازنشانی تنظیمات اطمینان دارید؟",
"reply_count": "{count} پاسخ",
"restore_preferences": "بازگرداندن تنظیمات به حالت پیش",
"piped_link": "پیوند Piped",
"import_from_json_csv": "وارد کردن از JSON/CSV",
"cancel": "لغو",
"enable_dearrow": "فعال کردن DeArrow",
"playlist_description": "شرح فهرست‌پخش",
"download_as_txt": "دریافت به صورت .txt",
"with_timecode": "اشتراک‌گذاری با مهر زمانی",
"source_code": "کد منبع",
"copy_link": "نسخه‌برداری از پیوند",
"dismiss": "رد کردن",
"hide_watched": "ویدیوهای تماشا شده را مخفی کنی",
"time_code": "مهر زمانی (به ثانیه)",
"chapters_layout_mobile": "جیدمان فصل‌های ویدیو روی موبایل",
"backup_preferences": "پشتیبان گیری از تنظیمات",
"instance_donations": "کمک مالی به سرویس دهنده",
"with_playlist": "اشتراک‌گذاری با فهرست‌پخش",
"store_search_history": "ذخیره کردن سابقهٔ جست و جو",
"share": "اشتراک‌گذاری",
"delete_automatically": "حذف خودکار پس از",
"show_less": "کمتر نشان بده",
"follow_link": "دنبال کردن پیوند",
"reset_preferences": "بازنشانی تنظیمات",
"download_frame": "دریافت قاب",
"create_group": "ساخت گروه",
"show_chapters": "فصل‌های ویدیو",
"back_to_home": "بازگشت به صفحهٔ اصلی",
"show_search_suggestions": "نمایش پیشنهادهای جست و جو",
"clone_playlist_success": "با موفقیت تکثیر شد!",
"instance_auth_selection": "سرویس‌دهندهٔ احراز هویت",
"documentation": "اسناد",
"different_auth_instance": "از سرویس‌دهندهٔ دیگری برای احراز هویت استفاده کنید",
"auto_display_captions": "نمایش خودکار زیرنویس",
"status_page": "وضعیت",
"show_watch_on_youtube": "نمایش دکمهٔ تماشا روی YouTube",
"generate_qrcode": "ساخت کد QR",
"playlist_name": "نام فهرست‌پخش",
"minimize_chapters_default": "کوچک کردن فصل‌های ویدیو به صورت پیش فرض",
"instance_privacy_policy": "سیاست حفظ حریم خصوصی",
"no_valid_playlists": "داخل فایل فهرست‌پخش معتبری وجود ندارد!",
"clone_playlist": "تکثیر فهرست‌پخش",
"playlist_bookmarked": "نشان‌دار شد",
"instances_not_shown": "سرویس‌دهنده‌های عمومی که این جا نشان داده نشده‌اند در حال حاضر در دسترس نیستند.",
"bookmark_playlist": "نشان‌دار",
"concurrent_prefetch_limit": "محدودیت پیش‌دریافت همزمان استریم"
},
"titles": {
"history": "تاریخچه",
@ -93,13 +145,24 @@
"bookmarks": "نشان‌دارها",
"livestreams": "پخش زنده",
"channels": "کانال‌ها",
"channel_groups": "گروه های کانال"
"channel_groups": "گروه های کانال",
"dearrow": "DeArrow"
},
"player": {
"watch_on": "تماشا روی {0}"
"watch_on": "تماشا روی {0}",
"failed": "عدم موفقیت با خطای {0}، برای اطلاعات بیشتر logها رو بررسی کنید"
},
"search": {
"did_you_mean": "منظورتان {0} بود؟"
"did_you_mean": "منظورتان {0} بود؟",
"all": "YouTube: همه",
"music_artists": "YT Music: هنرمندان",
"channels": "YouTube: کانال‌ها",
"music_albums": "YT Music: آلبوم‌ها",
"music_videos": "YT Music: ویدیوها",
"music_playlists": "YT Music: فهرست‌های پخش",
"playlists": "YouTube: فهرست‌های پخش",
"music_songs": "YT Music: آوازها",
"videos": "YouTube: ویدیوها"
},
"video": {
"views": "{views} بازدید ها",
@ -107,7 +170,15 @@
"watched": "دیده شده",
"sponsor_segments": "قسمت های اسپانسری",
"ratings_disabled": "رتبه بندی غیرفعال",
"chapters": "فصل ها"
"chapters": "فصل ها",
"all": "همه",
"live": "{0} زنده",
"shorts": "Shortها",
"license": "مجوز",
"category": "دسته‌بندی",
"chapters_vertical": "عمودی",
"chapters_horizontal": "افقی",
"visibility": "قابل مشاهده"
},
"preferences": {
"instance_locations": "محل های سرویس",
@ -115,13 +186,38 @@
"ssl_score": "امتیاز SSL",
"instance_name": "نام سرویس",
"version": "نسخه",
"registered_users": "کاربران تایید شده"
"registered_users": "کاربران تایید شده",
"up_to_date": "به روز؟",
"uptime_30d": "Uptime (30d)"
},
"comment": {
"pinned_by": "سنجاق شده توسط {author}"
"pinned_by": "سنجاق شده توسط {author}",
"loading": "دریافت نظرها…",
"user_disabled": "نظرها در تنظیمات غیرفعال شده‌اند.",
"disabled": "ارسال کننده، نظرها را غیرفعال کرده است."
},
"login": {
"username": "نام کاربری",
"password": "رمز"
"password": "رمز",
"password_confirm": "تایید رمز عبور",
"passwords_incorrect": "رمزهای عبور یکسان نیستند!"
},
"info": {
"hours": "{amount} ساعت",
"next_video_countdown": "پخش ویدیوی بعدی در {0} ثانیه",
"preferences_note": "توجه: تنظیمات در حافظهٔ داخلی مرورگر شما ذخیره می‌شوند. حذف اطلاعات مرورگر، تنظیمات را بازنشانی خواهد کرد.",
"local_storage": "این گزینه نیاز به localStorage دارد، آیا cookieها فعالند؟",
"cannot_copy": "نمی‌توان نسخه‌برداری کرد!",
"login_note": "با حساب کاربری ساخته شده در این سرویس دهنده وارد شوید.",
"months": "{amount} ماه",
"page_not_found": "صفحه پیدا نشد",
"weeks": "{amount} هفته",
"register_note": "در این سرویس دهندهٔ Piped حساب کاربری ایجاد کنید. به شما اجازه خواهد داد که اشتراک‌ها و فهرست‌های پخش را با حساب کاربری در سرویس‌دهنده همسان‌سازی کنید. می‌توانید از همهٔ امکانات بدون حساب کاربری استفاده کنید ولی تمام اطلاعات در حافظهٔ داخلی مرورگرتان ذخیره خواهد شد. لطفا مطمئن شوید که از ایمیل به جای نام کاربری استفاده نمی‌کنید و رمز عبور امنی انتخاب کنید که جای دیگری استفاده نشده است.",
"register_no_email_note": "استفاده از email به جای نام کاربری توصیه نمی‌شود. ادامه؟",
"days": "{amount} روز",
"copied": "نسخه‌برداری شد!"
},
"subscriptions": {
"subscribed_channels_count": "مشترک شده: {0}"
}
}

View file

@ -59,8 +59,8 @@
"most_recent": "Viimeisin",
"sort_by": "Järjestä:",
"view_subscriptions": "Näytä tilaukset",
"unsubscribe": "Poistu tilauksesta - {count}",
"subscribe": "Tilaa - {count}",
"unsubscribe": "Poistu tilauksesta",
"subscribe": "Tilaa",
"minimize_recommendations": "Minimoi suositukset",
"show_recommendations": "Näytä suositukset",
"hide_replies": "Piilota vastaukset",

View file

@ -14,11 +14,13 @@
"livestreams": "Diffusions en direct",
"channels": "Chaînes",
"bookmarks": "Marque-pages",
"channel_groups": "Groupes de chaînes"
"channel_groups": "Groupes de chaînes",
"dearrow": "DeArrow",
"albums": "Albums"
},
"actions": {
"subscribe": "S'abonner - {count}",
"unsubscribe": "Se désabonner - {count}",
"subscribe": "S'abonner",
"unsubscribe": "Se désabonner",
"buffering_goal": "Objectif de mise en mémoire tampon (en secondes)",
"skip_non_music": "Ignorer la musique : section non musicale",
"skip_self_promo": "Ignorer la promotion non rémunérée / l'autopromotion",
@ -28,12 +30,12 @@
"skip_intro": "Ignorer l'animation de l'entracte/Intro",
"skip_sponsors": "Ignorer les sponsors",
"instances_list": "Liste des instances",
"language_selection": "Sélection de la langue",
"language_selection": "Langue",
"store_watch_history": "Conserver l'historique de visionnage",
"minimize_description_default": "Minimiser la description par défaut",
"show_comments": "Afficher les commentaires",
"default_homepage": "Page d'accueil par défaut",
"country_selection": "Sélection du pays",
"country_selection": "Pays",
"autoplay_video": "Lire automatiquement la vidéo",
"light": "Clair",
"dark": "Sombre",
@ -46,7 +48,7 @@
"view_subscriptions": "Voir les abonnements",
"back": "Retour",
"uses_api_from": "Utilise l'API de ",
"sort_by": "Trier par :",
"sort_by": "Trier par :",
"channel_name_asc": "Nom de la chaîne (A-Z)",
"least_recent": "Le moins récent",
"most_recent": "Le plus récent",
@ -57,10 +59,10 @@
"donations": "Dons pour le développement",
"auto_play_next_video": "Lire la vidéo suivante automatiquement",
"loop_this_video": "Mettre cette vidéo en boucle",
"import_from_json": "Importer depuis le format JSON/CSV",
"import_from_json": "Importer depuis le format JSON",
"export_to_json": "Exporter en JSON",
"show_more": "Afficher plus",
"instance_selection": "Sélection de l'instance",
"instance_selection": "Instance",
"minimize_description": "Minimiser la description",
"minimize_recommendations": "Minimiser les recommandations",
"show_recommendations": "Afficher les recommandations",
@ -89,7 +91,7 @@
"minimize_recommendations_default": "Minimiser les recommandations par défaut",
"invalidate_session": "Se déconnecter de tous les appareils",
"different_auth_instance": "Utiliser une instance différente pour l'authentification",
"instance_auth_selection": "Sélection de l'instance d'authentification",
"instance_auth_selection": "Instance d'authentification",
"clone_playlist": "Cloner la liste de lecture",
"clone_playlist_success": "Clonage réussi !",
"download_as_txt": "Télécharger en tant que .txt",
@ -125,7 +127,7 @@
"min_segment_length": "Longueur minimale du segment (en secondes)",
"skip_segment": "Sauter le segment",
"show_less": "Afficher moins",
"okay": "OK",
"okay": "Valider",
"edit_playlist": "Éditer la liste de lecture",
"playlist_name": "Nom de la liste de lecture",
"auto_display_captions": "Afficher sous-titres automatiquement",
@ -136,10 +138,20 @@
"group_name": "Nom du groupe",
"autoplay_next_countdown": "Temps par défaut avant la prochaine vidéo (en secondes)",
"chapters_layout_mobile": "Format des chapitres sur mobile",
"show_search_suggestions": "Afficher les suggestions de recherche"
"show_search_suggestions": "Afficher les suggestions de recherche",
"add_to_group": "Ajouter au groupe",
"import_from_json_csv": "Importer depuis le format JSON/CSV",
"enable_dearrow": "Activer DeArrow",
"delete_automatically": "Supprimer automatiquement après",
"download_frame": "Télécharger la miniature",
"generate_qrcode": "Générer un QR code",
"instance_privacy_policy": "Politique de confidentialité",
"concurrent_prefetch_limit": "Limite de préchargements simultanés de flux",
"instances_not_shown": "Les instances publiques qui ne sont pas affichées ici sont actuellement indisponibles."
},
"player": {
"watch_on": "Regarder sur {0}"
"watch_on": "Voir sur {0}",
"failed": "Échec avec le code erreur {0}, voir les logs pour plus d'informations"
},
"video": {
"sponsor_segments": "Segments de sponsors",
@ -153,16 +165,19 @@
"all": "Tout",
"category": "Catégorie",
"chapters_horizontal": "Horizontal",
"chapters_vertical": "Vertical"
"chapters_vertical": "Vertical",
"visibility": "Visibilité",
"license": "Licence"
},
"preferences": {
"ssl_score": "Score SSL",
"has_cdn": "A un RDC ?",
"has_cdn": "A un CDN ?",
"instance_locations": "Localisations de l'instance",
"instance_name": "Nom de l'instance",
"up_to_date": "À jour ?",
"registered_users": "Utilisateurs enregistrés",
"version": "Version"
"version": "Version",
"uptime_30d": "Uptime (30j)"
},
"comment": {
"pinned_by": "Épinglé par {author}",
@ -172,7 +187,9 @@
},
"login": {
"password": "Mot de passe",
"username": "Nom d'utilisateur"
"username": "Nom d'utilisateur",
"password_confirm": "Confirmez le mot de passe",
"passwords_incorrect": "Les mots de passe ne correspondent pas !"
},
"search": {
"did_you_mean": "Vouliez-vous dire : {0} ?",
@ -183,7 +200,8 @@
"music_songs": "YT Music : Chansons",
"music_videos": "YT Music : Vidéos",
"music_playlists": "YT Music : Listes de lecture",
"music_albums": "YT Music : Albums"
"music_albums": "YT Music : Albums",
"music_artists": "YT Music : Artistes"
},
"subscriptions": {
"subscribed_channels_count": "Abonné à : {0}"
@ -198,6 +216,12 @@
"cannot_copy": "Impossible de copier !",
"local_storage": "Cette action nécessite localStorage, les cookies sont-ils activés ?",
"register_no_email_note": "Il n'est pas recommandé d'utiliser une adresse courriel omme nom d'utilisateur. Continuer quand même ?",
"next_video_countdown": "Lecture de la prochaine vidéo dans {0}s"
"next_video_countdown": "Lecture de la prochaine vidéo dans {0}s",
"hours": "{amount} heure(s)",
"login_note": "Se connecter avec un compte créé sur cette instance.",
"months": "{amount} mois",
"weeks": "{amount} semaine(s)",
"register_note": "Inscrivez-vous pour ce compte sur cette instance de Piped. Cela vous permettra de synchroniser vos abonnements et listes de lecture avec votre compte, afin qu'ils soient stockés côté serveur. Vous pouvez utiliser toutes les fonctionnalités sans avoir de compte, mais toutes les données seront stockées dans le cache local de votre navigateur. Assurez-vous de NE PAS utiliser une adresse e-mail comme nom d'utilisateur et choisissez un mot de passe sécurisé que vous n'utilisez pas ailleurs.",
"days": "{amount} jour(s)"
}
}

View file

@ -21,12 +21,12 @@
"failed": "Fallou con código do erro {0}, mira o rexistro para máis info"
},
"actions": {
"subscribe": "Subscribirse - {count}",
"subscribe": "Subscribirse",
"sort_by": "Orde por:",
"least_recent": "Máis antigo",
"most_recent": "Máis recente",
"channel_name_asc": "Nome da canle (A-Z)",
"unsubscribe": "Retirar subscrición - {count}",
"unsubscribe": "Retirar subscrición",
"view_subscriptions": "Ver Subscricións",
"back": "Volver",
"uses_api_from": "Usa a API desde ",

View file

@ -22,8 +22,8 @@
"failed": "חל כשל עם קוד שגיאה {0}, מידע נוסף ביומנים"
},
"actions": {
"subscribe": "מינוי - {count}",
"unsubscribe": "ביטול מינוי - {count}",
"subscribe": "מינוי",
"unsubscribe": "ביטול מינוי",
"view_subscriptions": "הצגת מינויים",
"sort_by": "מיון לפי:",
"most_recent": "האחרונים",
@ -147,7 +147,10 @@
"generate_qrcode": "יצירת קוד QR",
"import_from_json_csv": "ייבוא מ־JSON/CSV",
"download_frame": "הורדת תמונית",
"instance_privacy_policy": "מדיניות פרטיות"
"instance_privacy_policy": "מדיניות פרטיות",
"add_to_group": "הוספה לקבוצה",
"concurrent_prefetch_limit": "מגבלת משיכה טרומית של תזרימים במקביל",
"instances_not_shown": "מופעים ציבוריים שאינם מופיעים כאן אינם זמינים כרגע."
},
"comment": {
"pinned_by": "ננעץ על ידי {author}",
@ -162,7 +165,8 @@
"registered_users": "משתמשים רשומים",
"version": "גרסה",
"up_to_date": "עדכני?",
"ssl_score": "דירוג SSL"
"ssl_score": "דירוג SSL",
"uptime_30d": "זמן פעילות (30 ימים)"
},
"login": {
"username": "שם משתמש",
@ -209,7 +213,9 @@
"days": "{amount} ימים",
"weeks": "{amount} שבועות",
"months": "{amount} חודשים",
"hours": "{amount} שעות"
"hours": "{amount} שעות",
"login_note": "כניסה עם חשבון שנוצר בעותק הזה.",
"register_note": "הרשמה ל־Piped הזה. תאפשר לך לסנכרן את המינויים ואת רשימות הנגינה שלך עם החשבון שלך כך שיאוחסנו בצד השרת. אפשר להשתמש בכל התכונות בלי חשבון אך כל הנתונים יאוחסנו במטמון המקומי של הדפדפן שלך. נא לוודא שלא בחרת בכתובת דוא״ל כשם המשתמש שלך ורצוי לבחור בסיסמה מאובטחת שלא משמשת אותך בשום מקום אחר."
},
"subscriptions": {
"subscribed_channels_count": "נרשמת אל: {0}"

View file

@ -1,105 +1,234 @@
{
"titles": {
"trending": "ट्रेंडिंग",
"trending": "रुझान",
"history": "इतिहास",
"register": "रजिस्टर करें",
"login": "लॉग इन करें",
"preferences": "प्राथमिकताए",
"register": "पंजीकृत करें",
"login": "लॉगिन",
"preferences": "प्राथमिकताए",
"subscriptions": "सदस्यता",
"feed": "फीड",
"feed": "फीड",
"playlists": "प्लेलिस्ट",
"livestreams": "लाइव स्ट्रीम",
"livestreams": "लाइवस्ट्रीम",
"channels": "चैनल",
"player": "चालक",
"account": "खाता",
"instance": "इंस्टैंस"
"instance": "इंस्टैंस",
"channel_groups": "चैनल ग्रुप",
"bookmarks": "बुकमार्क",
"dearrow": "DeArrow",
"albums": "एलबम",
"custom_instances": "तदनुकूल इंस्टैंस"
},
"actions": {
"subscribe": "सदस्यता लें - {count}",
"back": "वापस जाओ",
"unsubscribe": "सदस्यता ले ली है - {count}",
"subscribe": "सदस्यता लें",
"back": "पीछे",
"unsubscribe": "सदस्यता छोड़ें",
"no": "नहीं",
"hide_replies": "जवाब छिपाएं",
"search": "खोजें (Ctrl+K)",
"loop_this_video": "इस वीडियो को लूप करें",
"loading": "लोड हो रहा है...",
"show_description": "विवरण दिखाएं",
"minimize_description": "विवरण छिपाएं",
"minimize_description": "विवरण संक्षेपित करें",
"yes": "हां",
"view_subscriptions": "सदस्यता देखें",
"most_recent": "सबसे हाला",
"least_recent": "कम से कम हाल का",
"channel_name_asc": "चैनल का नाम (ए-जेड)",
"channel_name_desc": "चैनल का नाम (जेड-ए)",
"uses_api_from": "से API का उपयोग करता है ",
"most_recent": "सबसे हालिया",
"least_recent": "कम हालिया",
"channel_name_asc": "चैनल नाम (A-Z)",
"channel_name_desc": "चैनल नाम (Z-A)",
"uses_api_from": "यहां से API का उपयोग करता है ",
"skip_sponsors": "प्रायोजकों को छोड़ें",
"skip_outro": "एंडकार्ड्स/क्रेडिट छोड़ें",
"skip_interaction": "इंटरैक्शन रिमाइंडर छोड़ें (सदस्यता लें)",
"skip_outro": "एंडकार्ड/क्रेडिट छोड़ें",
"skip_interaction": "इंटरेक्शन अनुस्मारक छोड़ें (सदस्यता लें)",
"theme": "थीम",
"dark": "डार्क",
"light": "प्रकाश",
"autoplay_video": "ऑटोप्ले वीडियो",
"audio_only": "सिर्फ़ ध्वनि",
"default_quality": "डिफ़ॉल्ट गुणवत्ता",
"dark": "गहरी",
"light": "हल्की",
"autoplay_video": "वीडियो स्वत:चालू करें",
"audio_only": "सिर्फ ऑडियो",
"default_quality": "तयशुदा गुणवत्ता",
"country_selection": "देश",
"show_comments": "टिप्पणियाँ दिखाएँ",
"store_watch_history": "स्टोर देखने का इतिहास",
"show_comments": "टिप्पणियां दिखाएं",
"store_watch_history": "देखने का इतिहास संग्रहीत करें",
"language_selection": "भाषा",
"instances_list": "इंस्टंस सूची",
"instance_selection": "इंस्टंस",
"show_more": "और दिखाओ",
"instances_list": "इंस्टंस सूची",
"instance_selection": "इंस्टंस",
"show_more": "अधिक दिखाएं",
"export_to_json": "JSON में निर्यात करें",
"import_from_json": "JSON/CSV से आयात करें",
"auto_play_next_video": "अगला वीडियो ऑटोप्ले करें",
"donations": "विकास दान",
"minimize_recommendations": "सिफारिशों को कम करें",
"show_recommendations": "सिफारिशें दिखाएं",
"import_from_json": "JSON से आयात करें",
"auto_play_next_video": "अगला वीडियो स्वत:चालू करें",
"donations": "विकास के लिए दान",
"minimize_recommendations": "अनुशंसाएं न्यूनतम करें",
"show_recommendations": "अनुशंसाएं दिखाएं",
"disable_lbry": "स्ट्रीमिंग के लिए LBRY अक्षम करें",
"enable_lbry_proxy": "LBRY के लिए प्रॉक्सी सक्षम करें",
"view_ssl_score": "एसएसएल स्कोर देखें",
"filter": "फिल्टर",
"clear_history": "स्पष्ट इतिहास",
"load_more_replies": "और जवाब लोड करें",
"view_ssl_score": "SSL स्कोर देखें",
"filter": "फिल्टर",
"clear_history": "इतिहास साफ़ करें",
"load_more_replies": "अधिक जवाब लोड करें",
"enabled_codecs": "सक्षम कोडेक्स (एकाधिक)",
"buffering_goal": "बफरिंग गोल (सेकंड में)",
"delete_playlist_confirm": "प्लेलिस्ट को मिटाना है?",
"buffering_goal": "बफरिंग क्ष्य (सेकंड में)",
"delete_playlist_confirm": "इस प्लेलिस्ट को मिटाएं?",
"add_to_playlist": "प्लेलिस्ट में जोड़ें",
"remove_from_playlist": "प्लेलिस्ट से निकाले",
"delete_playlist_video_confirm": "वीडियो को प्लेलिस्ट से निकालना है?",
"remove_from_playlist": "प्लेलिस्ट से हटाएं",
"delete_playlist_video_confirm": "प्लेलिस्ट से वीडियो हटाएं?",
"create_playlist": "प्लेलिस्ट बनायें",
"select_playlist": "एक प्लेलिस्ट चुनें",
"please_select_playlist": "कृपया एक प्लेलिस्ट चुनें",
"delete_playlist": "प्लेलिस्ट टाएं",
"enable_sponsorblock": "विज्ञापन प्रतिबंध करें",
"default_homepage": "स्वतः निर्धारित मुख्यपृष्ठ",
"sort_by": "वर्गीकरण:",
"select_playlist": "प्लेलिस्ट चुनें",
"please_select_playlist": "कृपया प्लेलिस्ट चुनें",
"delete_playlist": "प्लेलिस्ट मिटाएं",
"enable_sponsorblock": "स्पॉन्सरब्लॉक सक्षम करें",
"default_homepage": "यशुदा मुख्यपृष्ठ",
"sort_by": "ऐसे छांटें:",
"skip_automatically": "स्वतः",
"delete_account": "खाता मिटाएँ"
"delete_account": "खाता मिटाएं",
"skip_button_only": "स्किप बटन दिखाएं",
"skip_intro": "मध्यांतर/परिचय एनिमेशन छोड़ें",
"skip_self_promo": "अवैतनिक/स्व-प्रचार छोड़ें",
"skip_filler_tangent": "फिलर स्पर्शज्या छोड़ें",
"skip_non_music": "संगीत छोड़ें: गैर-संगीत अनुभाग",
"show_markers": "प्लेयर पर निशान दिखाएं",
"skip_preview": "पूर्वावलोकन/पुनर्कथनs छोड़ें",
"skip_highlight": "मुख्य आकर्षण छोड़ें",
"instance_auth_selection": "प्रमाणीकरण इंस्टैंस",
"different_auth_instance": "प्रमाणीकरण के लिए किसी भिन्न इंस्टैंस का उपयोग करें",
"reset_preferences": "प्राथमिकताएं रीसेट करें",
"back_to_home": "होम पर वापस",
"piped_link": "Piped लिंक",
"hide_watched": "देखी गई वीडियो फीड में छिपाएं",
"documentation": "दस्तावेज़ीकरण",
"status_page": "स्थिति",
"source_code": "स्रोत कोड",
"show_chapters": "अध्याय",
"follow_link": "लिंक का अनुसरण करें",
"store_search_history": "खोज इतिहास संग्रहित करें",
"copy_link": "लिंक कॉपी करें",
"with_timecode": "समय कोड के साथ साझा करें",
"edit_playlist": "प्लेलिस्ट संपादित करें",
"auto_display_captions": "अनुशीर्षक स्वत: प्रदर्शित करें",
"instances_not_shown": "जो सार्वजनिक इंस्टैंस यहां नहीं दिखाए जा रहे हैं, वे वर्तमान में अनुपलब्ध हैं।",
"enable_dearrow": "DeArrow सक्षम करें",
"auto": "स्वतः",
"minimize_description_default": "तयशुदा रूप से विवरण को संक्षेपित करें",
"import_from_json_csv": "JSON/CSV से आयात करें",
"logout": "इस उपकरण से लॉगआउट करें",
"chapters_layout_mobile": "मोबाइल पर अध्याय अभिन्यास",
"show_watch_on_youtube": "YouTube पर देखें बटन दिखाएं",
"invalidate_session": "सभी उपकरणों को लॉगआउट करें",
"clone_playlist": "प्लेलिस्ट की प्रतिलिपि बनाएं",
"clone_playlist_success": "सफलतापूर्वक प्रतिलिपि बनाई गई!",
"download_as_txt": ".txt के रूप में डाउनलोड करें",
"backup_preferences": "प्राथमिकताएं बैकअप करें",
"restore_preferences": "प्राथमिकताएं पुनर्स्थापित करें",
"playlist_name": "प्लेलिस्ट नाम",
"playlist_description": "प्लेलिस्ट विवरण",
"share": "साझा करें",
"time_code": "समय कोड (सेकंड में)",
"reply_count": "{count} जवाब",
"min_segment_length": "न्यूनतम खंड लंबाई (सेकंड में)",
"skip_segment": "खंड छोड़ें",
"autoplay_next_countdown": "अगले वीडियो तक तयशुदा उल्टीगिनती (सेकंड में)",
"minimize_comments_default": "तयशुदा रूप से टिप्पणियां संक्षेपित करें",
"minimize_comments": "टिप्पणियां को संक्षेपित करें",
"confirm_reset_preferences": "क्या आप वाकई अपनी प्राथमिकताएं रीसेट करना चाहते हैं?",
"no_valid_playlists": "फ़ाइल में मान्य प्लेलिस्ट नहीं हैं!",
"instance_privacy_policy": "गोपनीयता नीति",
"bookmark_playlist": "बुकमार्क करें",
"concurrent_prefetch_limit": "समवर्ती स्ट्रीम प्रीफ़ेच सीमा",
"cancel": "रद्द करें",
"okay": "ठीक है",
"playlist_bookmarked": "बुकमार्क किया गया",
"dismiss": "खारिज करें",
"show_less": "कम दिखाएं",
"create_group": "समूह बनाएं",
"group_name": "समूह नाम",
"show_search_suggestions": "खोज सुझाव दिखाएं",
"delete_automatically": "बाद में स्वचालित रूप से हटा दें",
"generate_qrcode": "QR कोड बनाएं",
"add_to_group": "समूह में जोड़ें",
"download_frame": "डाउनलोड फ्रेम",
"with_playlist": "प्लेलिस्ट के साथ साझा करें",
"instance_donations": "इंस्टैंस के लिए दान",
"minimize_chapters_default": "तयशुदा रूप से अध्यायों को न्यूनतम करें",
"minimize_recommendations_default": "तयशुदा रूप से अनुशंसाएं न्यूनतम करें",
"customize": "अनुकूलित करें",
"invalid_url": "अमान्य URL!",
"add": "जोड़ें",
"delete_group_confirm": "इस समूह को मिटाएं?",
"creator_replied": "निर्माता का जवाब",
"creator_liked": "निर्माता को पसंद",
"invalid_input": "अमान्य इनपुट",
"playback_speed": "प्लेबैक गति"
},
"video": {
"views": "{views} बार देखा गया",
"videos": "वीडियो",
"watched": "पहले ही देखा हुआ",
"watched": "देखा गया",
"ratings_disabled": "रेटिंग अक्षम",
"chapters": "चैप्टर",
"live": "{0} लाइव"
"chapters": "अध्याय",
"live": "{0} लाइव",
"sponsor_segments": "प्रायोजक खंड",
"shorts": "शॉर्ट्स",
"all": "सभी",
"category": "श्रेणी",
"license": "लाईसेंस",
"visibility": "दृश्यता",
"chapters_horizontal": "क्षैतिज",
"chapters_vertical": "ऊर्ध्वाधर"
},
"login": {
"password": "पासवर्ड",
"username": "उपयोगकर्ता नाम"
"username": "उपयोक्ता नाम",
"passwords_incorrect": "पासवर्ड मेल नहीं खाते हैं!",
"password_confirm": "पासवर्ड की पुष्टि करें"
},
"comment": {
"pinned_by": "{author} ने पिन किया"
"pinned_by": "{author} ने पिन किया",
"loading": "टिप्पणियां लोड हो रही हैं…",
"disabled": "टिप्पणियां अपलोडर द्वारा अक्षम की गई हैं।",
"user_disabled": "सेटिंग्स में टिप्पणियां अक्षम हैं।"
},
"preferences": {
"instance_locations": "इंस्टेंस स्थान",
"has_cdn": "सीडीएन है?",
"ssl_score": "एसएसएल स्कोर"
"instance_locations": "इंस्टैंस स्थान",
"has_cdn": "CDN है?",
"ssl_score": "SSL स्कोर",
"uptime_30d": "अपटाइम (30 दिन)",
"instance_name": "इंस्टैंस का नाम",
"registered_users": "पंजीकृत उपयोक्ता",
"version": "संस्करण",
"up_to_date": "अद्यतित?",
"api_url": "Api URL"
},
"search": {
"did_you_mean": "क्या आपका मतलब यह था: {0}?"
"did_you_mean": "क्या आपका मतलब यह था: {0}?",
"playlists": "YouTube: प्लेलिस्ट",
"music_videos": "YT Music: वीडियो",
"music_albums": "YT Music: एलबम",
"music_playlists": "YT Music: प्लेलिस्ट",
"all": "YouTube: सभी",
"videos": "YouTube: वीडियो",
"channels": "YouTube: चैनल्स",
"music_artists": "YT Music: कलाकार",
"music_songs": "YT Music: संगीत"
},
"player": {
"watch_on": "{0} में देखें"
"watch_on": "{0} पर देखें",
"failed": "त्रुटि कोड {0} के साथ विफल, अधिक जानकारी के लिए लॉग देखें"
},
"info": {
"login_note": "इस इंस्टैंस पर बनाए गए खाते से लॉग इन करें।",
"page_not_found": "पृष्ठ नहीं मिला",
"copied": "कॉपी किया गया!",
"cannot_copy": "कॉपी नहीं कर सकते!",
"local_storage": "यह क्रिया को लोकलस्टोरेज की आवश्यकता है, क्या कुकीज़ सक्षम हैं?",
"preferences_note": "नोट: प्राथमिकताएं आपके ब्राउज़र के स्थानीय संग्रहण में सहेजी जाती हैं। अपने ब्राउज़र डेटा को हटाने से वे रीसेट हो जाएंगी।",
"register_no_email_note": "उपयोक्ता नाम के रूप में ईमेल का उपयोग करने की अनुशंसा नहीं की जाती है। फिर भी आगे बढ़ें?",
"next_video_countdown": "अगला वीडियो {0} सेकंड में चलाया जा रहा है",
"hours": "{amount} घंटा(टे)",
"days": "{amount} दिन(नों)",
"weeks": "{amount} हफ्ता(ते)",
"months": "{amount} महीना(ने)",
"register_note": "Piped इंस्टैंस के लिए एक खाता पंजीकृत करें। इससे आप अपनी सदस्यता और प्लेलिस्ट को अपने खाते के साथ सिंक कर सकते हैं, ताकि वे सर्वर साइड पर संग्रहित हों। आप खाते के बिना भी सभी विशेषताएं इस्तेमाल कर सकते हैं, लेकिन सभी डेटा आपके ब्राउज़र के स्थानीय कैशे में संग्रहित होगा। कृपया सुनिश्चित करें कि आप अपना ईमेल पता उपयोक्ता नाम के रूप में इस्तेमाल नहीं कर रहे हैं और एक सुरक्षित पासवर्ड चुनें जिसे आप कहीं और नहीं इस्तेमाल करते हैं।"
},
"subscriptions": {
"subscribed_channels_count": "इसकी सदस्यता ली गई: {0}"
}
}

View file

@ -22,7 +22,9 @@
"instance_name": "Ime instance",
"registered_users": "Registrirani korisnici",
"version": "Verzija",
"up_to_date": "Najnovija verzija?"
"up_to_date": "Najnovija verzija?",
"uptime_30d": "Vrijeme rada (30 dana)",
"api_url": "URL Api-ja"
},
"comment": {
"pinned_by": "Prikvačio korisnik {author}",
@ -73,8 +75,8 @@
"most_recent": "Najnovije",
"sort_by": "Redoslijed:",
"view_subscriptions": "Pogledaj pretplate",
"unsubscribe": "Otkaži pretplatu {count}",
"subscribe": "Pretplati se {count}",
"unsubscribe": "Otkaži pretplatu",
"subscribe": "Pretplati se",
"skip_interaction": "Preskoči podsjetnik za interakciju (pretplata)",
"skip_outro": "Preskoči odjavnu špicu",
"skip_intro": "Preskoči pauzu i uvodnu animaciju",
@ -156,7 +158,14 @@
"generate_qrcode": "Generiraj QR kod",
"import_from_json_csv": "Uvezi iz JSON/CSV formata",
"download_frame": "Preuzmi kadar",
"instance_privacy_policy": "Politika privatnosti"
"instance_privacy_policy": "Politika privatnosti",
"add_to_group": "Dodaj grupi",
"instances_not_shown": "Javne instance koje ovdje nisu prikazane trenutačno nisu dostupne.",
"concurrent_prefetch_limit": "Ograničenje istodobnog preuzimanja videa",
"customize": "Prilagodi",
"invalid_url": "Neispravni URL!",
"add": "Dodaj",
"delete_group_confirm": "Izbrisati ovu grupu?"
},
"player": {
"watch_on": "Gledaj na {0}",
@ -178,7 +187,9 @@
"livestreams": "Prijenosi uživo",
"bookmarks": "Zabilješke",
"channel_groups": "Grupe kanala",
"dearrow": "DeArrow"
"dearrow": "DeArrow",
"albums": "Albumi",
"custom_instances": "Prilagođene instance"
},
"login": {
"password": "Lozinka",
@ -215,6 +226,8 @@
"hours": "{amount} h",
"days": "{amount} dan(a)",
"weeks": "{amount} tj",
"months": "{amount} mj"
"months": "{amount} mj",
"login_note": "Prijavi se s računom stvorenim na ovoj instanci.",
"register_note": "Registriraj račun za ovu Piped instancu. To će ti omogućiti sinkronizaciju tvojih pretplata i playlista s tvojim računom kako bi se spremile na poslužitelju. Možeš koristiti sve značajke bez računa, ali će se svi podaci spremiti u lokalnu predmemoriju tvog preglednika. NEMOJ koristiti e-mail adresu kao korisničko ime i odaberi sigurnu lozinku koju ne koristiš negdje drugdje."
}
}

View file

@ -12,14 +12,19 @@
"player": "Lejátszó",
"instance": "Szerver",
"livestreams": "Élő adások",
"channels": "Csatornák"
"channels": "Csatornák",
"dearrow": "DeArrow",
"albums": "Albumok",
"bookmarks": "Könyvjelzők",
"channel_groups": "Csatorna csoportok",
"custom_instances": "Egyéni példányok"
},
"actions": {
"subscribe": "Feliratkozás - {count}",
"subscribe": "Feliratkozás",
"skip_highlight": "Kiemelés",
"light": "Világos",
"most_recent": "Legutóbbi",
"unsubscribe": "Leiratkozás - {count}",
"unsubscribe": "Leiratkozás",
"view_subscriptions": "Feliratkozások megtekintése",
"least_recent": "Legrégebbi",
"channel_name_asc": "Csatorna név (A-Z)",
@ -39,12 +44,12 @@
"autoplay_video": "Automatikus lejátszás",
"audio_only": "Csak hang",
"default_quality": "Alapértelmezett minőség",
"country_selection": "Ország választás",
"country_selection": "Ország",
"default_homepage": "Alapértelmezett kezdőlap",
"show_comments": "Megjegyzések megjelenítése",
"minimize_description_default": "Leírás minimalizásása alapból",
"store_watch_history": "Megtekintési előzmények tárolása",
"language_selection": "Nyelv választás",
"language_selection": "Nyelv",
"enabled_codecs": "Engedélyezett kodekek (több)",
"show_more": "További megjelenítése",
"yes": "Igen",
@ -52,14 +57,14 @@
"export_to_json": "Exportálás JSON-ba",
"skip_preview": "Előzetes/Ismétlés",
"buffering_goal": "Pufferelési cél (másodpercben)",
"instance_selection": "Példány kiválasztása",
"instance_selection": "Példány",
"skip_filler_tangent": "Témától eltérő töltelék/viccek",
"loop_this_video": "Videó ismétlése",
"donations": "Fejlesztési támogatások",
"minimize_description": "Leírás minimalizálása",
"show_recommendations": "Javaslatok megjelenítése",
"enable_lbry_proxy": "Proxy engedélyezése a LBRY számára",
"search": "Keresés",
"search": "Keresés (Ctrl+K)",
"filter": "Szűrés",
"loading": "Betöltés...",
"clear_history": "Megtekintési előzmények törlése",
@ -75,7 +80,7 @@
"view_ssl_score": "SSL pontszám megtekintése",
"sort_by": "Rendezés:",
"show_description": "Leírás megjelenítése",
"import_from_json": "Importálás JSON/CSV-ból",
"import_from_json": "Importálás JSON-ból",
"delete_playlist_video_confirm": "Eltávolítja a videót a lejátszási listából?",
"remove_from_playlist": "Törlés a lejátszási listából",
"auto_play_next_video": "Következő videó automatikus lejátszása",
@ -87,7 +92,7 @@
"minimize_recommendations_default": "Ajánlások alapértelmezett minimalizálása",
"invalidate_session": "Kijelentkezés minden eszközről",
"different_auth_instance": "Másik példány használata a hitelesítéshez",
"instance_auth_selection": "Autentikációs példány kiválasztása",
"instance_auth_selection": "Hitelesítési példány",
"clone_playlist": "Lejátszási lista klónozása",
"clone_playlist_success": "Sikeresen klónozva!",
"reset_preferences": "Alaphelyzetbe állítás",
@ -107,7 +112,7 @@
"backup_preferences": "Beállítások mentése",
"share": "Megosztás",
"with_timecode": "Megosztás & videó kezdés ettől a ponttól",
"store_search_history": "Mentse a keresési előzményeket",
"store_search_history": "Keresési előzmények tárolása",
"follow_link": "Követések link",
"copy_link": "Link másolása",
"status_page": "Státusz",
@ -115,7 +120,43 @@
"with_playlist": "Megosztás lejátszási listával",
"minimize_comments_default": "Mindig tüntesd el a kommenteket",
"minimize_comments": "Kommentek eltüntetése",
"back_to_home": "Vissza a főoldalra"
"back_to_home": "Vissza a főoldalra",
"delete_automatically": "Automatikus törlés ezt követően",
"enable_dearrow": "DeArrow engedélyezése",
"playlist_name": "Lejátszási lista neve",
"instance_privacy_policy": "Adatvédelmi szabályzat",
"cancel": "Visszavonás",
"okay": "Rendben",
"concurrent_prefetch_limit": "Egyidejű adatfolyam előzetes letöltési korlátja",
"bookmark_playlist": "Könyvjelző",
"dismiss": "Elvetés",
"show_less": "Mutass kevesebbet",
"create_group": "Csoport létrehozása",
"playlist_bookmarked": "Könyvjelzőzött",
"edit_playlist": "Lejátszási lista szerkesztése",
"group_name": "Csoport neve",
"min_segment_length": "Minimális szegmens hossz (másodpercben)",
"skip_automatically": "Automatikusan",
"instances_not_shown": "Az itt nem látható nyilvános példányok jelenleg nem érhetők el.",
"skip_button_only": "Kihagyás gomb megjelenítése",
"autoplay_next_countdown": "Alapértelmezett visszaszámlálás a következő videóig (másodpercben)",
"import_from_json_csv": "Importálás JSON/CSV formátumból",
"auto_display_captions": "Feliratok automatikus megjelenítése",
"chapters_layout_mobile": "Fejezetek elrendezése telefonon",
"skip_segment": "Szegmens kihagyása",
"playlist_description": "Lejátszási lista leírása",
"show_search_suggestions": "Mutass keresési javaslatokat",
"generate_qrcode": "QR-kód generálása",
"add_to_group": "Hozzáadás a csoporthoz",
"download_frame": "Keret letöltése",
"customize": "Testreszab",
"invalid_url": "Érvénytelen URL!",
"add": "Hozzáadás",
"delete_group_confirm": "Törli ezt a csoportot?",
"creator_replied": "A készítő válaszolt",
"creator_liked": "A készítő kedvelte",
"playback_speed": "Visszajátszási sebesség",
"invalid_input": "Érvénytelen bevitel"
},
"video": {
"ratings_disabled": "Értékelések Letiltva",
@ -125,10 +166,17 @@
"live": "{0} Élő",
"videos": "Videók",
"views": "{views} megtekintés",
"shorts": "Rövid videók"
"shorts": "Rövid videók",
"category": "Kategória",
"chapters_horizontal": "Vízszintes",
"chapters_vertical": "Függőleges",
"all": "Mind",
"license": "Licenc",
"visibility": "Láthatóság"
},
"player": {
"watch_on": "Lejátszásban {0}"
"watch_on": "Megtekintés itt: {0}",
"failed": "Sikertelen hibakód: {0}, további információért tekintse meg a naplókat"
},
"preferences": {
"instance_name": "Példány neve",
@ -137,7 +185,9 @@
"version": "Verzió",
"ssl_score": "SSL pontszám",
"registered_users": "Regisztrált felhasználók",
"up_to_date": "Naprakész?"
"up_to_date": "Naprakész?",
"uptime_30d": "Üzemidő (30 nap)",
"api_url": "Api URL"
},
"search": {
"did_you_mean": "Erre gondoltál: {0}?",
@ -148,11 +198,14 @@
"music_songs": "YT Music: Dalok",
"music_videos": "YT Music: Videók",
"music_albums": "YT Music: Albumok",
"music_playlists": "YT Music: Lejátszási listák"
"music_playlists": "YT Music: Lejátszási listák",
"music_artists": "YT Zene: Előadók"
},
"login": {
"username": "Felhasználónév",
"password": "Jelszó"
"password": "Jelszó",
"password_confirm": "Jelszó megerősítése",
"passwords_incorrect": "A jelszavak nem egyeznek!"
},
"comment": {
"pinned_by": "Rögzítette {author}",
@ -168,6 +221,14 @@
"copied": "Másolva!",
"local_storage": "Ennek a beállításnak szüksége van a \"lokális tárhely\" funkcióra, be vannak a sütik kapcsolva?",
"cannot_copy": "Nem lehet másolni!",
"page_not_found": "Oldnal nem található"
"page_not_found": "Oldnal nem található",
"register_no_email_note": "Nem ajánlott e-mailt használni felhasználónévként. Tovább folytatja?",
"next_video_countdown": "Következő videó lejátszása {0}másodperc múlva",
"weeks": "{amount} hét",
"login_note": "Jelentkezzen be az ezen a példányon létrehozott fiókkal.",
"months": "{amount} hónap",
"hours": "{amount} óra",
"days": "{amount} nap",
"register_note": "Regisztráljon egy fiókot ehhez a Piped példányhoz. Ez lehetővé teszi az előfizetések és lejátszási listák szinkronizálását a fiókjával, így azok a kiszolgáló oldalon kerülnek tárolásra. Az összes funkciót fiók nélkül is használhatja, de minden adat a böngésző helyi gyorsítótárában tárolódik. Kérjük, győződjön meg róla, hogy NE használjon e-mail címet felhasználónévként, és válasszon biztonságos jelszót, amelyet máshol nem használ."
}
}

View file

@ -1,7 +1,7 @@
{
"actions": {
"skip_automatically": "Ավտոմատվաց",
"subscribe": "Բաժանորդ - {count}",
"subscribe": "Բաժանորդ",
"uses_api_from": "Օգտագործում է API -ից ",
"enable_sponsorblock": "Միացնել հովանավորների արգելափակումը",
"skip_intro": "Բաց թողնել ընդմիջում/ներածական անիմացիա",

View file

@ -15,18 +15,20 @@
"channels": "Saluran",
"bookmarks": "Markah",
"channel_groups": "Grup saluran",
"dearrow": "DeArrow"
"dearrow": "DeArrow",
"albums": "Album",
"custom_instances": "Server khusus"
},
"player": {
"watch_on": "Lihat di {0}",
"failed": "Gagal dengan kode kesalahan {0}, lihat catatan untuk info lebih lanjut"
},
"actions": {
"subscribe": "Berlangganan - {count}",
"subscribe": "Berlangganan",
"view_subscriptions": "Lihat Langganan",
"sort_by": "Sortir bedasarkan oleh:",
"least_recent": "Baru",
"unsubscribe": "Berhenti Berlangganan - {count}",
"unsubscribe": "Berhenti Berlangganan",
"channel_name_asc": "Nama Saluran (A-Z)",
"channel_name_desc": "Nama Saluran (Z-A)",
"back": "Kembali",
@ -147,7 +149,13 @@
"generate_qrcode": "Buat Kode QR",
"import_from_json_csv": "Impor dari JSON/CSV",
"download_frame": "Unduh bingkai",
"instance_privacy_policy": "Kebijakan Privasi"
"instance_privacy_policy": "Kebijakan Privasi",
"add_to_group": "Tambahkan ke grup",
"concurrent_prefetch_limit": "Batasan Concurrent Stream Prefetch",
"instances_not_shown": "Instance publik yang tidak ditampilkan disini saat ini tidak tersedia.",
"customize": "Ubah",
"add": "Tambahkan",
"invalid_url": "URL tidak valid!"
},
"comment": {
"pinned_by": "Dipasangi pin oleh {author}",
@ -162,7 +170,9 @@
"has_cdn": "Memakai CDN?",
"up_to_date": "Sudah terkini?",
"version": "Versi",
"registered_users": "Pengguna Terdaftar"
"registered_users": "Pengguna Terdaftar",
"uptime_30d": "Waktu aktif (30hari)",
"api_url": "URL API"
},
"login": {
"username": "Nama Pengguna",
@ -215,6 +225,8 @@
"weeks": "{amount} minggu",
"hours": "{amount} jam",
"days": "{amount} hari",
"months": "{amount} bulan"
"months": "{amount} bulan",
"login_note": "Masuk dengan akun yang dibuat di server ini.",
"register_note": "Daftarkan akun untuk server Piped ini. Ini akan memungkinkan Anda untuk menyinkronkan langganan dan daftar putar Anda dengan akun Anda, sehingga mereka disimpan di sisi server. Anda dapat menggunakan semua fitur tanpa akun, tetapi semua data akan disimpan di tembolok lokal browser Anda. Pastikan Anda TIDAK menggunakan alamat surel sebagai nama pengguna Anda dan pilih kata sandi yang aman yang tidak Anda gunakan di tempat lain."
}
}

View file

@ -23,8 +23,8 @@
"light": "Ljós",
"theme": "Þema",
"enable_sponsorblock": "Virkja Sponsorblock",
"subscribe": "Gerast Áskrifandi - {count}",
"unsubscribe": "Segja Upp Áskrift - {count}",
"subscribe": "Gerast Áskrifandi",
"unsubscribe": "Segja Upp Áskrift",
"auto": "Sjálfvirkt",
"audio_only": "Aðeins Hljóð",
"most_recent": "Nýlegast",

View file

@ -31,8 +31,8 @@
"least_recent": "Meno recente",
"sort_by": "Ordina per:",
"view_subscriptions": "Visualizza gli abbonamenti",
"unsubscribe": "Disiscriviti - {count}",
"subscribe": "Iscriviti - {count}",
"unsubscribe": "Disiscriviti",
"subscribe": "Iscriviti",
"enabled_codecs": "Abilita Codecs (Molteplici)",
"enable_lbry_proxy": "Abilita il proxy per LBRY",
"disable_lbry": "Disabilita LBRY per lo streaming",
@ -43,7 +43,7 @@
"donations": "Donazioni per lo sviluppo",
"auto_play_next_video": "Riproduci automaticamente il prossimo video",
"loop_this_video": "Ripeti questo video",
"import_from_json": "Importa da JSON/CSV",
"import_from_json": "Importa da JSON",
"export_to_json": "Esporta in JSON",
"no": "No",
"yes": "Sì",
@ -88,7 +88,7 @@
"follow_link": "Apri il collegamento",
"with_timecode": "Condividi con marca temporale",
"show_chapters": "Capitoli",
"store_search_history": "Memorizza la cronologia delle ricerche",
"store_search_history": "Archivia la cronologia delle ricerche",
"status_page": "Stato",
"documentation": "Documentazione",
"source_code": "Codice sorgente",
@ -117,10 +117,21 @@
"group_name": "Nome gruppo",
"create_group": "Crea gruppo",
"show_search_suggestions": "Mostra suggerimenti di ricerca",
"dismiss": "Chiudi"
"dismiss": "Chiudi",
"add_to_group": "Aggiungi al gruppo",
"import_from_json_csv": "Importa da JSON/CSV",
"enable_dearrow": "Abilita DeArrow",
"chapters_layout_mobile": "Disposizione dei capitoli sul cellulare",
"delete_automatically": "Cancella automaticamente dopo",
"auto_display_captions": "Visualizza automaticamente i sottotitoli",
"generate_qrcode": "Genera un codice QR",
"instance_privacy_policy": "Normativa sulla privacy",
"download_frame": "Scarica fotogramma",
"instances_not_shown": "Le istanze pubbliche che non compaiono in questa schermata non sono al momento disponibili."
},
"player": {
"watch_on": "Guarda su {0}"
"watch_on": "Guarda su {0}",
"failed": "Operazione non riuscita (codice errore {0}). Vedi il registro per ulteriori dettagli"
},
"titles": {
"history": "Cronologia",
@ -137,7 +148,8 @@
"livestreams": "Streaming live",
"channels": "Canali",
"bookmarks": "Segnalibri",
"dearrow": "DeArrow"
"dearrow": "DeArrow",
"channel_groups": "Gruppi di canali"
},
"video": {
"sponsor_segments": "Segmenti sponsor",
@ -152,7 +164,8 @@
"category": "Categoria",
"chapters_horizontal": "Orizzontale",
"chapters_vertical": "Verticale",
"license": "Licenza"
"license": "Licenza",
"visibility": "Visibilità"
},
"preferences": {
"ssl_score": "Valutazione SSL",
@ -171,7 +184,9 @@
},
"login": {
"password": "Password",
"username": "Nome utente"
"username": "Nome utente",
"password_confirm": "Conferma password",
"passwords_incorrect": "Le password non combaciano!"
},
"search": {
"did_you_mean": "Forse intendevi: {0}?",
@ -198,6 +213,12 @@
"cannot_copy": "Impossibile copiare!",
"local_storage": "Questa azione richiede localStorage, i cookie sono abilitati?",
"register_no_email_note": "L'utilizzo di un indirizzo e-mail come nome utente è sconsigliato. Continuare comunque?",
"next_video_countdown": "Riproduzione prossimo video tra {0}s"
"next_video_countdown": "Riproduzione prossimo video tra {0}s",
"login_note": "Accedi con un account creato su questa istanza.",
"register_note": "Registra un account per questa istanza di Piped. Ciò ti consentirà di sincronizzare le tue iscrizioni e le tue playlist con il tuo account, in modo che siano archiviate sul server. È possibile utilizzare tutte le funzionalità anche senza un account, ma tutti i dati verranno archiviati nella memoria locale del tuo browser. Assicurati di NON utilizzare un indirizzo email come nome utente e di scegliere una password sicura che non usi altrove.",
"hours": "{amount} ora/e",
"months": "{amount} mese/i",
"weeks": "{amount} settimana/e",
"days": "{amount} giorno/i"
}
}

View file

@ -3,7 +3,7 @@
"trending": "急上昇",
"login": "ログイン",
"register": "新規登録",
"feed": "フィード",
"feed": "新着動画",
"preferences": "設定",
"history": "履歴",
"subscriptions": "登録チャンネル",
@ -15,15 +15,17 @@
"livestreams": "ライブ配信",
"bookmarks": "ブックマーク",
"channel_groups": "グループ",
"dearrow": "DeArrow"
"dearrow": "DeArrow",
"albums": "アルバム",
"custom_instances": "独自インスタンス"
},
"player": {
"watch_on": "{0}で視聴",
"failed": "失敗しエラーコード {0} が返りました。詳細はログに記録"
"failed": "失敗。エラーコード {0} 。詳細はログに記録"
},
"actions": {
"subscribe": "チャンネル登録 - {count}",
"unsubscribe": "登録解除 - {count}",
"subscribe": "チャンネル登録",
"unsubscribe": "登録解除",
"view_subscriptions": "登録チャンネルを見る",
"sort_by": "表示順:",
"most_recent": "新しい順",
@ -35,7 +37,7 @@
"enable_sponsorblock": "SponsorBlock を使用",
"skip_sponsors": "広告をスキップ",
"skip_intro": "合間/導入アニメをスキップ",
"skip_outro": "終了シーン/クレジットをスキップ",
"skip_outro": "終了画面/クレジットをスキップ",
"skip_preview": "予告/あらすじをスキップ",
"skip_interaction": "登録など操作を頼む自己宣伝をスキップ",
"skip_self_promo": "無償または自己の宣伝をスキップ",
@ -102,7 +104,7 @@
"download_as_txt": ".txtでダウンロード",
"logout": "この端末からログアウト",
"minimize_recommendations_default": "最初からおすすめを最小化",
"hide_watched": "再生済みの動画をフィードに表示しない",
"hide_watched": "再生済みの動画を新着動画に表示しない",
"minimize_chapters_default": "最初からチャプターを最小化",
"show_watch_on_youtube": "「YouTubeで視聴」ボタンを表示",
"invalidate_session": "すべての端末からログアウト",
@ -112,8 +114,8 @@
"restore_preferences": "設定を復元",
"back_to_home": "ホームに戻る",
"copy_link": "リンクコピー",
"time_code": "タイムコード (秒)",
"documentation": "ドキュメント",
"time_code": "開始時間 (秒)",
"documentation": "説明書",
"reset_preferences": "設定を初期化",
"confirm_reset_preferences": "設定をリセットしますか?",
"piped_link": "Pipedリンク",
@ -144,10 +146,17 @@
"show_search_suggestions": "検索語句の候補を表示",
"delete_automatically": "指定時間後に自動削除",
"enable_dearrow": "DeArrow を使用",
"generate_qrcode": "QRコード生成",
"generate_qrcode": "QRコード 生成",
"import_from_json_csv": "JSON/CSVから読み込む",
"download_frame": "この画像を保存",
"instance_privacy_policy": "個人情報保護方針"
"instance_privacy_policy": "個人情報保護方針",
"add_to_group": "グループに追加",
"instances_not_shown": "現在利用できない公開インスタンスはここに表示されません。",
"concurrent_prefetch_limit": "同時に先読みするストリーム数上限",
"add": "追加",
"invalid_url": "無効なURLです",
"customize": "追加",
"delete_group_confirm": "このグループを削除しますか?"
},
"comment": {
"pinned_by": "{author} によって固定",
@ -162,7 +171,9 @@
"ssl_score": "SSLの評価",
"registered_users": "登録利用者数",
"version": "バージョン",
"up_to_date": "最新?"
"up_to_date": "最新?",
"uptime_30d": "稼働率(30日)",
"api_url": "API の URL"
},
"login": {
"username": "ユーザー名",
@ -209,7 +220,9 @@
"days": "{amount}日",
"weeks": "{amount}週",
"hours": "{amount}時間",
"months": "{amount}月"
"months": "{amount}月",
"login_note": "このインスタンス用に作成したアカウントにログインできます。",
"register_note": "この Piped インスタンス用にアカウントを作成します。登録チャンネルと再生リストを同期するために、それらの情報をサーバー内に保存します。アカウントなしでもすべての機能を使用できますが、その場合、すべてのデータは端末内のブラウザーのキャッシュとして保存されます。ユーザー名にメールアドレスを使用しないでください。他のサービスで使っていない安全なパスワードを登録してください。"
},
"subscriptions": {
"subscribed_channels_count": "チャンネル登録: {0}"

View file

@ -40,8 +40,8 @@
"remove_from_playlist": "Kkes seg tebdart n tɣuri",
"delete_playlist_video_confirm": "Kkes tavidyut seg tebdart n tɣuri?",
"create_playlist": "Rnu tabdart n tɣuri",
"subscribe": "Qqen - {count}",
"unsubscribe": "Sefsex tuqqna n - {count}",
"subscribe": "Qqen",
"unsubscribe": "Sefsex tuqqna n",
"view_subscriptions": "Wali imuktaɣen",
"sort_by": "Semyizwer s:",
"most_recent": "Amaynut akk",

View file

@ -6,7 +6,7 @@
"hide_replies": "답글 숨기기",
"skip_interaction": "상호 작용 알림 (구독) 스킵",
"show_comments": "댓글 보이기",
"unsubscribe": "구독 취소 - {count}",
"unsubscribe": "구독 취소",
"view_subscriptions": "구독 보기",
"least_recent": "오래된 순",
"theme": "테마",
@ -20,9 +20,9 @@
"skip_non_music": "음악: 음악이 아닌 구간 스킵",
"skip_self_promo": "셀프 프로모션 스킵",
"buffering_goal": "버퍼링 목표 (초)",
"country_selection": "국가 선택",
"country_selection": "국가",
"store_watch_history": "시청 기록 저장",
"language_selection": "언어 선택",
"language_selection": "언어",
"no": "아니요",
"loop_this_video": "이 동영상 반복",
"auto_play_next_video": "다음 동영상 자동 재생",
@ -31,14 +31,14 @@
"sort_by": "정렬:",
"most_recent": "최신 순",
"channel_name_asc": "채널 이름 (A-Z)",
"subscribe": "구독 - {count}",
"subscribe": "구독",
"audio_only": "오디오만",
"skip_sponsors": "스폰서 스킵",
"dark": "다크",
"minimize_description_default": "설명 가리기를 기본 설정값으로",
"enabled_codecs": "활성화된 코덱 (여러 개)",
"instance_selection": "인스턴스 선택",
"import_from_json": "JSON/CSV에서 가져오기",
"instance_selection": "인스턴스",
"import_from_json": "JSON에서 가져오기",
"light": "라이트",
"autoplay_video": "동영상 자동 재생",
"default_quality": "기본 화질",
@ -84,7 +84,7 @@
"back_to_home": "홈으로 가기",
"minimize_recommendations_default": "추천 동영상 가리기를 기본 설정값으로",
"invalidate_session": "모든 기기에서 로그아웃",
"instance_auth_selection": "인증 인스턴스 선택",
"instance_auth_selection": "인증 인스턴스",
"different_auth_instance": "인증에 다른 인스턴스 사용",
"clone_playlist": "재생목록 복제",
"clone_playlist_success": "성공적으로 복제되었습니다!",
@ -103,7 +103,32 @@
"autoplay_next_countdown": "다음 영상 재생까지 대기 시간(초)",
"skip_button_only": "스킵 버튼 표시",
"skip_automatically": "자동",
"show_less": "덜 보기"
"show_less": "덜 보기",
"create_group": "그룹 만들기",
"reply_count": "{count}개의 댓글",
"import_from_json_csv": "JSON/CSV에서 가져오기",
"concurrent_prefetch_limit": "동시에 스트림을 미리 받아두는 한도",
"no_valid_playlists": "이 파일은 올바른 플레이리스트를 갖고 있지 않습니다!",
"with_playlist": "플레이리스트와 함께 공유",
"playlist_description": "플레이리스트 설명",
"group_name": "그룹 이름",
"cancel": "취소",
"okay": "예",
"download_frame": "프레임 다운로드",
"auto_display_captions": "자동으로 자막 표시",
"instances_not_shown": "이곳에 보이지 않는 공개 인스턴스는 현재 이용할 수 없습니다.",
"min_segment_length": "최소 세그먼트 길이 (초 단위)",
"skip_segment": "세그먼트 건너뛰기",
"enable_dearrow": "DeArrow 활성화",
"chapters_layout_mobile": "모바일에서의 챕터 레이아웃",
"edit_playlist": "플레이리스트 편집",
"playlist_name": "플레이리스트 이름",
"playlist_bookmarked": "북마크됨",
"delete_automatically": "자동으로 삭제하기 시작하는 시간은",
"generate_qrcode": "QR 코드 생성",
"add_to_group": "그룹에 추가",
"instance_privacy_policy": "개인정보 보호 정책",
"show_search_suggestions": "검색 추천을 표시"
},
"titles": {
"feed": "피드",
@ -119,10 +144,13 @@
"player": "플레이어",
"bookmarks": "북마크",
"livestreams": "실시간",
"channels": "채널"
"channels": "채널",
"dearrow": "",
"channel_groups": "채널 그룹"
},
"player": {
"watch_on": "에서 보기 {0}"
"watch_on": "{0}에서 보기",
"failed": "에러 코드 {0}로 인해 실패했습니다. 더 많은 정보는 로그를 확인해주세요"
},
"comment": {
"pinned_by": "에 의해 고정됨 {author}",
@ -137,11 +165,14 @@
"instance_name": "인스턴스 이름",
"registered_users": "등록 된 사용자",
"version": "버전",
"up_to_date": "최신 버전?"
"up_to_date": "최신 버전?",
"uptime_30d": "가동률 (30일 동안)"
},
"login": {
"username": "유저 이름",
"password": "비밀번호"
"password": "비밀번호",
"password_confirm": "비밀번호 확인",
"passwords_incorrect": "비밀번호가 일치하지 않습니다!"
},
"video": {
"videos": "동영상",
@ -152,7 +183,12 @@
"live": "{0} 라이브",
"shorts": "Shorts",
"chapters": "챕터",
"category": "카테고리"
"category": "카테고리",
"all": "모두",
"license": "라이선스",
"visibility": "가시성",
"chapters_horizontal": "가로 방향",
"chapters_vertical": "수직 방향"
},
"search": {
"did_you_mean": "이것을 찾으셨나요: {0}?",
@ -163,13 +199,23 @@
"channels": "YouTube: 채널",
"playlists": "YouTube: 재생목록",
"music_videos": "YT Music: 동영상",
"music_albums": "YT Music: 앨범"
"music_albums": "YT Music: 앨범",
"music_artists": "유튜브 뮤직: 아티스트"
},
"info": {
"cannot_copy": "복사할 수 없습니다!",
"copied": "복사되었습니다!",
"preferences_note": "참고: 설정은 브라우저 로컬 저장소에 저장됩니다. 브라우저 데이터를 삭제하면 초기화됩니다.",
"page_not_found": "페이지를 찾을 수 없음"
"page_not_found": "페이지를 찾을 수 없음",
"local_storage": "이 액션은 localStorage가 필요합니다만, 쿠키가 활성화 되어있는지 확인해주실래요?",
"register_note": "계정을 이 Piped 인스턴스에 등록합니다. 이것은 당신의 구독 목록과 재생 목록을 서버에 보존하여 어디서든 동기화할 수 있게 해줍니다. 물론 계정 없이도 모든 기능을 쓸 순 있지만, 모든 데이터들은 당신이 사용중인 브라우저의 로컬 캐쉬에 저장될 것입니다. 메일주소는 \"절대\" 유저명으로 쓰지 말고, 비밀번호는 다른 곳에서 쓰지 않는 것으로 만들어주세요.",
"register_no_email_note": "이메일 주소를 유저명으로 쓰는건 추천하지 않습니다. 그래도 계속할까요?",
"next_video_countdown": "다음 동영상을 {0}초 안에 재생함",
"hours": "{amount}시간",
"login_note": "이 인스턴스에 생성된 계정으로 로그인합니다.",
"days": "{amount}일",
"weeks": "{amount}주",
"months": "{amount}달"
},
"subscriptions": {
"subscribed_channels_count": "구독: {0}"

View file

@ -1,7 +1,7 @@
{
"actions": {
"unsubscribe": "Atšaukti prenumeratą - {count}",
"subscribe": "Prenumeruoti - {count}",
"unsubscribe": "Atšaukti prenumeratą",
"subscribe": "Prenumeruoti",
"instances_list": "Perdavimo šaltinių sąrašas",
"language_selection": "Kalbos pasirinkimas",
"store_watch_history": "Saugoti žiūrėjimo istoriją",

230
src/locales/lv.json Normal file
View file

@ -0,0 +1,230 @@
{
"actions": {
"okay": "Labi",
"edit_playlist": "Rediģēt Atskaņošanas Sarakstu",
"group_name": "Grupas nosaukums",
"invalidate_session": "Izrakstīties no visām ierīcēm",
"playlist_bookmarked": "Grāmatzīme Izveidota",
"add_to_group": "Pievienot grupai",
"confirm_reset_preferences": "Vai Jūs vēlaties atiestatīt Jūsu iestatījumus?",
"reply_count": "{count} atbildes",
"restore_preferences": "Restaurēt Iestatījumus",
"piped_link": "Piped saite",
"buffering_goal": "Video Priekšielādes Ilgums (sekundēs)",
"skip_button_only": "Rādīt izlaist pogu",
"minimize_comments_default": "Paslēpt Komentārus pēc Noklusējuma",
"import_from_json_csv": "Importēt no JSON/CSV",
"auto": "Automātisks",
"skip_outro": "Izlaist Atzīšanas Titrus",
"cancel": "Atcelt",
"enable_dearrow": "Ieslēgt DeArrow",
"channel_name_asc": "Kanāla nosaukums (A-Z)",
"playlist_description": "Atskaņošanas Saraksta Apraksts",
"download_as_txt": "Lejupielādēt kā .txt",
"with_timecode": "Dalīties ar laika kodu",
"source_code": "Pirmkods",
"skip_intro": "Izlaist Starpbrīža/Ievada Animāciju",
"copy_link": "Kopēt saiti",
"auto_play_next_video": "Automātiski Atskaņot Nākošo Video",
"instance_selection": "Instance",
"dismiss": "Noraidīt",
"subscribe": "Abonēt",
"clear_history": "Tīrīt Vēsturi",
"loading": "Ielādē...",
"minimize_description": "Paslēpt Aprakstu",
"skip_interaction": "Izlaist Interakcijas atgādinājumu (Abonēt)",
"hide_watched": "Paslēpt skatītos video saturā",
"time_code": "Laika kods (sekundēs)",
"filter": "Filtrs",
"view_ssl_score": "Rādīt SSL Vērtējumu",
"delete_account": "Dzēst Kontu",
"minimize_description_default": "Paslēpt Aprakstu pēc Noklusējuma",
"chapters_layout_mobile": "Nodaļu Izvietojums un Mobilajām Ierīcēm",
"unsubscribe": "Atcelt abonomentu",
"channel_name_desc": "Kanāla nosaukums (Z-A)",
"backup_preferences": "Dublēt Iestatījumus",
"language_selection": "Valoda",
"instance_donations": "Ziedojumi instancei",
"with_playlist": "Dalīties ar atskaņošanas sarakstu",
"enable_lbry_proxy": "Ieslēgt Starpniekserveri priekš LBRY",
"donations": "Ziedojumi Izstrādei",
"store_search_history": "Saglabāt Skatījumu Vēsturi",
"share": "Dalīties",
"delete_automatically": "Automātiski dzēst vēlāk",
"show_less": "Rādīt mazāk",
"loop_this_video": "Atkārtoti Atskaņot Video",
"follow_link": "Atvērt saiti",
"theme": "Motīvs",
"logout": "Izrakstīties no šīs ierīces",
"reset_preferences": "Atiestatīt Iestatījumus",
"dark": "Tumšais",
"download_frame": "Lejupielādēt kadru",
"create_group": "Izveidot grupu",
"hide_replies": "Paslēpt Atbildes",
"least_recent": "Senākie",
"show_chapters": "Nodaļas",
"select_playlist": "Izvēlēties Atskaņošanas Sarakstu",
"most_recent": "Jaunākie",
"country_selection": "Valsts",
"back_to_home": "Atpakaļ uz Sākumlapu",
"skip_self_promo": "Izlaist Neapmaksātu/Pašreklamēšanu",
"default_quality": "Noklusējuma Kvalitāte",
"show_more": "Rādīt Vairāk",
"show_recommendations": "Rādīt Ieteikumus",
"skip_segment": "Izlaist Segmentu",
"delete_playlist": "Dzēst Atskaņošanas Sarakstu",
"minimize_recommendations": "Paslēpt Ieteikumus",
"show_search_suggestions": "Rādīt meklēšanas ieteikumus",
"audio_only": "Tikai Audio",
"skip_filler_tangent": "Izlaist Nesaistītu Saturu",
"disable_lbry": "Izslēgt LBRY Priekš Straumēšanas",
"show_comments": "Rādīt Komentārus",
"store_watch_history": "Saglabāt Skatījumu Vēsturi",
"clone_playlist_success": "Veiksmīgi klonēts!",
"no": "Nē",
"create_playlist": "Izveidot Atskaņošanas Sarakstu",
"instance_auth_selection": "Autentifikācijas Instance",
"yes": "Jā",
"documentation": "Dokumentācija",
"skip_sponsors": "Izlaist Sponsorus",
"sort_by": "Kārtot pēc:",
"delete_playlist_video_confirm": "Vai noņemt video no atskaņošanas saraksta?",
"back": "Atpakaļ",
"different_auth_instance": "Izmantot citu instanci autentifikācijai",
"load_more_replies": "Ielādēt vēl Atbildes",
"enabled_codecs": "Ieslēgtie Kodeki (vairāki)",
"auto_display_captions": "Automātiski Attēlot Subtitrus",
"minimize_comments": "Paslēpt Komentārus",
"view_subscriptions": "Skatīt abonomentus",
"skip_automatically": "Automātiski",
"status_page": "Statuss",
"skip_non_music": "Mūzikā Izlaist Nemūzikas Sadaļu",
"show_markers": "Rādīt Iezīmes Atskaņotājā",
"instances_list": "Instanču saraksts",
"autoplay_video": "Automātiski Atskaņot Video",
"show_watch_on_youtube": "Rādīt Skatīties ar YouTube pogu",
"import_from_json": "Importēt no JSON",
"autoplay_next_countdown": "Noklusējuma laiks līdz nākamajam video (sekundēs)",
"generate_qrcode": "Izveidot QR Kodu",
"enable_sponsorblock": "Ieslēgt Sponsorblock",
"playlist_name": "Atskaņošanas Saraksta Nosaukums",
"default_homepage": "Noklusējuma Sākumlapa",
"minimize_chapters_default": "Paslēpt Nodaļas pēc Noklusējuma",
"instance_privacy_policy": "Konfidencialitātes politika",
"minimize_recommendations_default": "Paslēpt Atskaņošanas Sarakstu pēc Noklusējuma",
"remove_from_playlist": "Noņemt no Atskaņošanas Saraksta",
"search": "Meklēt (Ctrl+K)",
"show_description": "Rādīt Aprakstu",
"light": "Gaišais",
"no_valid_playlists": "Fails nesatur derīgus atskaņošanas sarakstus!",
"skip_preview": "Izlaist Kopsavilkumu",
"please_select_playlist": "Izvēlieties Atskaņošanas Sarakstu",
"skip_highlight": "Izlaist uz Būtisko Momentu",
"export_to_json": "Eksportēt uz JSON",
"min_segment_length": "Minimālā Segmenta Garums (sekundēs)",
"delete_playlist_confirm": "Vai vēlaties dzēst šo atskaņošanas sarakstu?",
"bookmark_playlist": "Izveidot Grāmatzīmi",
"clone_playlist": "Klonēt Atskaņošanas Saturu",
"uses_api_from": "Izmanto API no ",
"add_to_playlist": "Pievienot Atskaņošanas Sarakstam",
"instances_not_shown": "Publiskās instances, kas šeit nav redzamas, pašlaik nav pieejamas.",
"delete_group_confirm": "Vai vēlaties dzēst šo grupu?",
"concurrent_prefetch_limit": "Vienlaicīgu Straumju Ielādes Limits",
"customize": "Pielāgot",
"invalid_url": "Nederīgs URL!",
"add": "Pievienot"
},
"search": {
"all": "YouTube: Visi",
"music_artists": "YT Music: Izpildītāji",
"did_you_mean": "Vai jūs domājāt: {0}?",
"channels": "YouTube: Kanāli",
"music_albums": "YT Music: Albumi",
"music_videos": "YT Music: Video",
"music_playlists": "YT Music: Atskaņošanas Saraksti",
"playlists": "YouTube: Atskaņošanas Saraksti",
"music_songs": "YT Music: Dziesmas",
"videos": "YouTube: Video"
},
"player": {
"watch_on": "Atskaņot uz {0}",
"failed": "Kļūda ar kodu {0}, papildus informācija pieejama žurnālos"
},
"titles": {
"subscriptions": "Abonomenti",
"trending": "Tendences",
"livestreams": "Straumes",
"login": "Ienākt",
"preferences": "Iestatījumi",
"feed": "Saturs",
"channel_groups": "Kanālu grupas",
"account": "Konts",
"instance": "Instance",
"history": "Vēsture",
"bookmarks": "Grāmatzīmes",
"channels": "Kanāli",
"playlists": "Atskaņošanas saraksts",
"register": "Reģistrēties",
"player": "Atskaņotājs",
"dearrow": "DeArrow",
"albums": "Albumi",
"custom_instances": "Pielāgotas instances"
},
"video": {
"all": "Visi",
"live": "{0} Skatītāji",
"shorts": "Shorts",
"ratings_disabled": "Vērtējumi atspējoti",
"visibility": "Redzamība",
"videos": "Video",
"license": "Licenze",
"category": "Kategorija",
"chapters": "Nodaļas",
"chapters_vertical": "Vertikāli",
"watched": "Skatīts",
"chapters_horizontal": "Horizontāli",
"sponsor_segments": "Sponsoru Sadaļas",
"views": "{views} skatījumi"
},
"info": {
"hours": "{amount} stunda/-as",
"next_video_countdown": "Atskaņo video pēc {0}s",
"preferences_note": "Piezīme: iestatījumi tiek saglabāti pārlūkprogrammas vietējā krātuvē. Izdzēšot pārlūkprogrammas datus, tie tiks atiestatīti.",
"local_storage": "Šai darbībai nepieciešams localStorage, vai sīkdatnes ir ieslēgtas?",
"cannot_copy": "Nevar kopēt!",
"login_note": "Ienākt ar kontu, kas izveidots šajā instancē.",
"months": "{amount} mēnesis/-ši",
"page_not_found": "Lapa nav atrasta",
"weeks": "{amount} nedēļa/-as",
"register_note": "Reģistrējiet kontu šai Piped instancei. Jums būs iespējams sinhronizēt abonomentus un atskaņošanas sarakstus, kas tiks saglabāti serverī. Visas funkcijas Jūs varat izmantot bez konta, bet visi Jūsu dati tiks saglabāti vietējā pārlūkprogrammas kešatmiņā. Lūdzu, pārliecinieties, ka nelietojat e-pasta adresi kā lietotājvārdu, un izvēlieties drošu paroli, ko neizmantojat citur.",
"register_no_email_note": "Nav ieteicams izmantot e-pastu kā lietotājvārdu. Vai turpināt?",
"days": "{amount} diena/-as",
"copied": "Kopēts!"
},
"comment": {
"loading": "Ielādē komentārus...",
"user_disabled": "Komentāri ir izslēgti iestatījumos.",
"disabled": "Augšupielādētājs atspējoja komentārus.",
"pinned_by": "{author} piesprauda"
},
"preferences": {
"ssl_score": "SSL Vērtējums",
"version": "Versija",
"up_to_date": "Jaunākā versija?",
"has_cdn": "Vai ir satura piegādes tīkls?",
"instance_name": "Instances Nosaukums",
"registered_users": "Reģistrētie Lietotāji",
"instance_locations": "Instances Atrašanās Vietas",
"uptime_30d": "Darbspējas laiks (30d)",
"api_url": "Api URL"
},
"login": {
"username": "Lietotājvārds",
"password": "Parole",
"password_confirm": "Apstiprināt paroli",
"passwords_incorrect": "Paroles nav vienādas!"
},
"subscriptions": {
"subscribed_channels_count": "Abonēts: {0}"
}
}

View file

@ -13,8 +13,8 @@
},
"actions": {
"view_subscriptions": "സബ്സ്ക്രിപ്ഷനുകൾ കാണുക",
"unsubscribe": "സബ്സ്ക്രൈബ് ചെയ്യേണ്ട - {count}",
"subscribe": "സബ്സ്ക്രൈബ് ചെയ്യുക - {count}",
"unsubscribe": "സബ്സ്ക്രൈബ് ചെയ്യേണ്ട",
"subscribe": "സബ്സ്ക്രൈബ് ചെയ്യുക",
"instances_list": "ഇൻസ്റ്റൻസുകളുടെ പട്ടിക",
"minimize_description_default": "സ്ഥിരമായി വിവരണം ചെറുതാക്കുക",
"skip_intro": "ഇടവേള/ആമുഖ ആനിമേഷൻ ഒഴിവാക്കുക",

View file

@ -31,8 +31,8 @@
"most_recent": "Nyest",
"sort_by": "Sorter etter:",
"view_subscriptions": "Vis abonnementer",
"unsubscribe": "Opphev abonnement - {count}",
"subscribe": "Abonner - {count}",
"unsubscribe": "Opphev abonnement",
"subscribe": "Abonner",
"enable_lbry_proxy": "Skru på mellomtjener for LBRY",
"disable_lbry": "Skru av LBRY-strømming",
"enabled_codecs": "Aktiverte forskjellige kodek",

View file

@ -14,14 +14,14 @@
"filter": "Filter",
"skip_filler_tangent": "Opvultangens Overslaan",
"theme": "Thema",
"subscribe": "Abonneren - {count}",
"subscribe": "Abonneren",
"skip_non_music": "Muziek Overslaan: Niet-muzieksectie",
"show_comments": "Opmerkingen tonen",
"skip_self_promo": "Onbetaalde-/zelfpromotie overslaan",
"skip_highlight": "Markering Overslaan",
"skip_interaction": "Interactieherinnering overslaan (abonneren)",
"show_more": "Meer tonen",
"unsubscribe": "Afmelden - {count}",
"unsubscribe": "Afmelden",
"view_subscriptions": "Abonnementen bekijken",
"enable_sponsorblock": "Sponsorblok inschakelen",
"skip_preview": "Voorbeschouwing/samenvatting overslaan",
@ -125,7 +125,14 @@
"auto_display_captions": "Ondertiteling automatisch tonen",
"import_from_json_csv": "Importeren uit JSON/CSV",
"download_frame": "Beeld downloaden",
"instance_privacy_policy": "Privacybeleid"
"instance_privacy_policy": "Privacybeleid",
"add_to_group": "Toevoegen aan groep",
"instances_not_shown": "Openbare gevallen die hier niet worden weergegeven, zijn momenteel niet beschikbaar.",
"concurrent_prefetch_limit": "Limiet voor gelijk­tijdige stream-prefetching",
"customize": "Aanpassen",
"add": "Toevoegen",
"invalid_url": "Ongeldige URL!",
"delete_group_confirm": "Deze groep verwijderen?"
},
"titles": {
"register": "Registreren",
@ -134,19 +141,21 @@
"preferences": "Voorkeuren",
"history": "Geschiedenis",
"subscriptions": "Abonnementen",
"trending": "Trending",
"playlists": "Afspeellijsten",
"trending": "Populair",
"playlists": "Afspeel­sten",
"account": "Account",
"instance": "Instantie",
"player": "Speler",
"livestreams": "Livestreams",
"channels": "Kanalen",
"bookmarks": "Bladwijzers",
"bookmarks": "Blad­zers",
"dearrow": "DeArrow",
"channel_groups": "Kanaal­groepen"
"channel_groups": "Kanaal­groepen",
"albums": "Albums",
"custom_instances": "Aangepaste instanties"
},
"player": {
"watch_on": "Bekijken op {0}",
"watch_on": "Bekijken op {0}",
"failed": "Mislukt met foutcode {0}, zie logboeken voor meer informatie"
},
"search": {
@ -190,7 +199,9 @@
"instance_locations": "Instantielocaties",
"version": "Versie",
"up_to_date": "Bijgewerkt?",
"ssl_score": "SSL-score"
"ssl_score": "SSL-score",
"uptime_30d": "Uptime (30d)",
"api_url": "Api-URL"
},
"comment": {
"pinned_by": "Vastgemaakt door {author}",
@ -209,7 +220,9 @@
"days": "{amount} dag(en)",
"weeks": "{amount} week/weken",
"months": "{amount} maand(en)",
"hours": "{amount} uur"
"hours": "{amount} uur",
"login_note": "Log in met een account dat op deze instantie is aangemaakt.",
"register_note": "Registreer een account voor deze Piped-instantie. Hierdoor kunt u uw abonnementen en afspeellijsten synchroniseren met uw account, zodat ze aan de serverkant worden opgeslagen. U kunt alle functies gebruiken zonder account, maar alle gegevens worden opgeslagen in de lokale cache van uw browser. Zorg ervoor dat u GEEN e-mailadres als gebruikersnaam gebruikt en kies een veilig wachtwoord dat u niet elders gebruikt."
},
"subscriptions": {
"subscribed_channels_count": "Geabonneerd op: {0}"

View file

@ -15,15 +15,17 @@
"playlists": "Listas de lecturas",
"bookmarks": "Marcapaginas",
"channel_groups": "Grops de cadenas",
"dearrow": "DeArrow"
"dearrow": "DeArrow",
"albums": "Albums",
"custom_instances": "Instàncias personalizadas"
},
"player": {
"watch_on": "Veire sus {0}",
"failed": "Fracàs amb lo còdi derror {0}, consultat los jornals daudit per mai dinformacions"
},
"actions": {
"subscribe": "Sabonar - {count}",
"unsubscribe": "Se desabonar - {count}",
"subscribe": "Sabonar",
"unsubscribe": "Se desabonar",
"view_subscriptions": "Veire los abonaments",
"sort_by": "Triar per:",
"most_recent": "Mai recents",
@ -147,7 +149,13 @@
"delete_automatically": "Suprimir automaticament aprèp",
"download_frame": "Telecargar fotograma",
"generate_qrcode": "Generar un còdi QR",
"instance_privacy_policy": "Politica de confidencialitat"
"instance_privacy_policy": "Politica de confidencialitat",
"add_to_group": "Apondre al grop",
"instances_not_shown": "Las instàncias publicas que se veson pas aicí son pas disponiblas actualament.",
"customize": "Personalizar",
"invalid_url": "URL invalida !",
"concurrent_prefetch_limit": "Limit de precargament de flux simultanèus",
"add": "Ajustar"
},
"preferences": {
"instance_locations": "Localizacion de linstància",
@ -156,7 +164,9 @@
"has_cdn": "A un CDN ?",
"version": "Version",
"up_to_date": "Actualizat ?",
"ssl_score": "Marca SSL"
"ssl_score": "Marca SSL",
"api_url": "URL de l'Api",
"uptime_30d": "Temps d'activitat (30 jorns)"
},
"login": {
"username": "Nom dutilizaire",
@ -191,7 +201,8 @@
"hours": "{amount} ora(s)",
"months": "{amount} mes(es)",
"days": "{amount} jorn(s)",
"weeks": "{amount} setmana(s)"
"weeks": "{amount} setmana(s)",
"login_note": "Se connectar amb un compte creat sus aquesta instància."
},
"comment": {
"disabled": "Lautor a desactivat los comentaris.",

View file

@ -22,8 +22,8 @@
"failed": "ତ୍ରୁଟି ସଂକେତ {0} ସହିତ ବିଫଳ, ଅଧିକ ସୂଚନା ପାଇଁ ଲଗଗୁଡ଼ିକୁ ଦେଖନ୍ତୁ"
},
"actions": {
"subscribe": "ସଦସ୍ୟତା - {count}",
"unsubscribe": "ସଦସ୍ୟତା ରଦ୍ଦ କରନ୍ତୁ - {count}",
"subscribe": "ସଦସ୍ୟତା",
"unsubscribe": "ସଦସ୍ୟତା ରଦ୍ଦ କରନ୍ତୁ",
"view_subscriptions": "ସଦସ୍ୟତା ଗୁଡ଼ିକ ଦେଖନ୍ତୁ",
"sort_by": "ଏହି କ୍ରମରେ ସଜାନ୍ତୁ:",
"most_recent": "ସଦ୍ୟତମ",
@ -147,7 +147,10 @@
"cancel": "ବାତିଲ କରନ୍ତୁ",
"import_from_json_csv": "JSON/CSV ରୁ ଆମଦାନୀ କରନ୍ତୁ",
"download_frame": "ଫ୍ରେମକୁ ଆହରଣ କରନ୍ତୁ",
"instance_privacy_policy": "ଗୋପନୀୟତା ନୀତି"
"instance_privacy_policy": "ଗୋପନୀୟତା ନୀତି",
"add_to_group": "ସମୂହରେ ଯୋଗ କରନ୍ତୁ",
"instances_not_shown": "ଏଠାରେ ଦର୍ଶାଯାଇନଥିବା ସାର୍ବଜନୀନ ଉଦାହରଣଗୁଡ଼ିକ ବର୍ତ୍ତମାନ ଉପଲବ୍ଧ ନାହିଁ ।",
"concurrent_prefetch_limit": "ସମସାମୟିକ ପ୍ରବାହ ପ୍ରାକ ଫେଚ୍ ସୀମା"
},
"comment": {
"loading": "ମନ୍ତବ୍ୟ ଲୋଡ୍ ହେଉଛି ...",
@ -197,7 +200,9 @@
"hours": "{amount} ଘଣ୍ଟା",
"days": "{amount} ଦିନ",
"weeks": "{amount} ସପ୍ତାହ",
"months": "{amount} ମାସ"
"months": "{amount} ମାସ",
"login_note": "ଏହି ପରିପ୍ରେକ୍ଷୀରେ ନିର୍ମିତ ଏକ ଖାତା ସହିତ ଲଗଇନ କରନ୍ତୁ ।",
"register_note": "ଏହି ପାଇପ ଉଦାହରଣ ପାଇଁ ଏକ ଖାତା ପଞ୍ଜିକରଣ କରନ୍ତୁ । ଏହା ଆପଣଙ୍କୁ ଆପଣଙ୍କର ସବସ୍କ୍ରିପସନ ଏବଂ ପ୍ଲେଲିଷ୍ଟଗୁଡ଼ିକୁ ଆପଣଙ୍କର ଖାତା ସହିତ ସିଙ୍କ କରିବାକୁ ଅନୁମତି ଦେବ, ତେଣୁ ସେଗୁଡ଼ିକ ସର୍ଭର ପାର୍ଶ୍ୱରେ ସଂରକ୍ଷିତ ହୋଇଥାଏ । ଆପଣ ଏକାଉଣ୍ଟ ବିନା ସମସ୍ତ ବୈଶିଷ୍ଟ୍ୟ ବ୍ୟବହାର କରିପାରିବେ, କିନ୍ତୁ ସମସ୍ତ ତଥ୍ୟ ଆପଣଙ୍କର ବ୍ରାଉଜରର ସ୍ଥାନୀୟ କ୍ୟାଶେରେ ସଂରକ୍ଷିତ ହେବ । ଦୟାକରି ନିଶ୍ଚିତ କରନ୍ତୁ ଯେ ଆପଣ ଗୋଟିଏ ଇମେଲ ଠିକଣାକୁ ଆପଣଙ୍କର ଚାଳକ ନାମ ଭାବରେ ବ୍ୟବହାର କରିବେ ନାହିଁ ଏବଂ ଏକ ସୁରକ୍ଷିତ ପ୍ରବେଶ ସଂକେତ ବାଛନ୍ତୁ ଯାହାକୁ ଆପଣ ଅନ୍ୟ କୌଣସି ସ୍ଥାନରେ ବ୍ୟବହାର କରିବେ ନାହିଁ ।"
},
"preferences": {
"instance_name": "ଇନଷ୍ଟାନ୍ସ ନାମ",
@ -206,7 +211,8 @@
"instance_locations": "ଇନଷ୍ଟାନ୍ସ ଅବସ୍ଥାନ",
"has_cdn": "CDN ଅଛି କି?",
"up_to_date": "ଅଦ୍ୟାବଧି?",
"ssl_score": "SSL ସ୍କୋର"
"ssl_score": "SSL ସ୍କୋର",
"uptime_30d": "ସମୟ ଅପରିବର୍ତ୍ତନୀୟ (30d)"
},
"login": {
"password": "ପାସୱାର୍ଡ",

View file

@ -15,15 +15,17 @@
"channels": "Kanały",
"bookmarks": "Zakładki",
"channel_groups": "Grupy kanałów",
"dearrow": "DeArrow"
"dearrow": "DeArrow",
"albums": "Albumy",
"custom_instances": "Niestandardowe instancje"
},
"player": {
"watch_on": "Zobacz na {0}",
"failed": "Niepowodzenie z powodu kodu błędu {0}, przejrzyj logi, aby uzyskać więcej informacji"
},
"actions": {
"subscribe": "Subskrybuj - {count}",
"unsubscribe": "Odsubskrybuj - {count}",
"subscribe": "Subskrybuj",
"unsubscribe": "Odsubskrybuj",
"view_subscriptions": "Zarządzaj subskrybcjami",
"sort_by": "Sortuj:",
"most_recent": "Najnowsze",
@ -43,7 +45,7 @@
"skip_highlight": "Przechodź do meritum filmu",
"skip_filler_tangent": "Pomijaj wstawki humorystyczne",
"theme": "Motyw",
"auto": "Automatyczna",
"auto": "Automatyczny",
"dark": "Ciemny",
"light": "Jasny",
"autoplay_video": "Autoodtwarzanie",
@ -147,7 +149,18 @@
"generate_qrcode": "Wygeneruj kod QR",
"import_from_json_csv": "Import z pliku JSON/CSV",
"download_frame": "Pobierz klatkę",
"instance_privacy_policy": "Polityki prywatności"
"instance_privacy_policy": "Polityki prywatności",
"add_to_group": "Dodaj do grupy",
"instances_not_shown": "Instancje publiczne, które nie są tutaj pokazane, są obecnie niedostępne.",
"concurrent_prefetch_limit": "Limit równoczesnego pobierania wstępnego strumienia",
"customize": "Dostosuj",
"invalid_url": "Nieprawidłowy adres URL!",
"add": "Dodaj",
"delete_group_confirm": "Usunąć tę grupę?",
"creator_replied": "Twórca odpowiedział",
"creator_liked": "Twórca polubił",
"invalid_input": "Nieprawidłowe dane wejściowe",
"playback_speed": "Szybkość odtwarzania"
},
"comment": {
"pinned_by": "Przypięty przez {author}",
@ -162,7 +175,9 @@
"registered_users": "Zarejestrowani użytkownicy",
"version": "Wersja",
"up_to_date": "Aktualna?",
"ssl_score": "Ocena SSL"
"ssl_score": "Ocena SSL",
"uptime_30d": "Czas pracy (30d)",
"api_url": "Adres URL interfejsu API"
},
"login": {
"username": "Nazwa użytkownika",
@ -209,7 +224,9 @@
"days": "{amount} dni",
"weeks": "{amount} tygodnie",
"hours": "{amount} godziny",
"months": "{amount} miesiące"
"months": "{amount} miesiące",
"login_note": "Zaloguj się na konto utworzone w tej instancji.",
"register_note": "Zarejestruj konto dla tej instancji Piped. Umożliwi to synchronizację subskrypcji i list odtwarzania z twoim kontem, dzięki czemu będą one przechowywane po stronie serwera. Możesz korzystać ze wszystkich funkcji bez konta, ale wszystkie dane będą przechowywane w lokalnej pamięci podręcznej Twojej przeglądarki. Upewnij się, że NIE używasz adresu e-mail jako nazwy użytkownika i wybierz bezpieczne hasło, którego nie używasz nigdzie indziej."
},
"subscriptions": {
"subscribed_channels_count": "Licznik subskrybcji: {0}"

View file

@ -15,7 +15,9 @@
"channels": "Canais",
"bookmarks": "Marcadores",
"channel_groups": "Grupos de canais",
"dearrow": "DeArrow"
"dearrow": "DeArrow",
"albums": "Álbuns",
"custom_instances": "Instâncias personalizadas"
},
"actions": {
"sort_by": "Ordenar por:",
@ -25,9 +27,9 @@
"back": "Recuar",
"uses_api_from": "Utiliza a \"API\" de ",
"enable_sponsorblock": "Ativar \"SponsorBlock\"",
"skip_intro": "Ignorar intermissão/animação de introdução",
"skip_outro": "Ignorar \"Endcards\"/Créditos",
"skip_preview": "Ignorar pré-visualização/recapitulando",
"skip_intro": "Ignorar intromissão/animação de introdução",
"skip_outro": "Ignorar cartões finais/créditos",
"skip_preview": "Ignorar pré-visualização/recapitulação",
"auto": "Automático",
"dark": "Escuro",
"autoplay_video": "Reproduzir vídeos automaticamente",
@ -36,7 +38,7 @@
"country_selection": "País",
"default_homepage": "Página inicial padrão",
"show_comments": "Mostrar comentários",
"minimize_description_default": "Minimizar descrição por omissão",
"minimize_description_default": "Por definição, minimizar descrição",
"store_watch_history": "Guardar histórico de visualizações",
"instances_list": "Lista de instâncias",
"enabled_codecs": "Codificadores ativados (vários)",
@ -52,13 +54,13 @@
"show_recommendations": "Mostrar recomendações",
"disable_lbry": "Desativar \"LBRY\" para emissões",
"enable_lbry_proxy": "Ativar proxy para \"LBRY\"",
"view_ssl_score": "Ver avaliação \"SSL\"",
"view_ssl_score": "Ver avaliação SSL",
"search": "Pesquisa (Ctrl+K)",
"filter": "Filtrar",
"loading": "A carregar...",
"clear_history": "Limpar histórico",
"subscribe": "Subscrever - {count}",
"unsubscribe": "Anular subscrição - {count}",
"subscribe": "Subscrever",
"unsubscribe": "Anular subscrição",
"view_subscriptions": "Ver subscrições",
"channel_name_desc": "Nome do canal (Z-A)",
"skip_sponsors": "Ignorar patrocínios",
@ -77,9 +79,9 @@
"buffering_goal": "Objetivo de 'buffer' (em segundos)",
"skip_filler_tangent": "Ignorar segmentos de preenchimento",
"add_to_playlist": "Adicionar à lista de reprodução",
"delete_playlist": "Apagar lista de reprodução",
"delete_playlist": "Eliminar lista de reprodução",
"select_playlist": "Selecionar uma lista de reprodução",
"delete_playlist_confirm": "Apagar esta lista de reprodução?",
"delete_playlist_confirm": "Eliminar esta lista de reprodução?",
"please_select_playlist": "Selecione uma lista de reprodução",
"delete_playlist_video_confirm": "Remover vídeo da lista de reprodução?",
"remove_from_playlist": "Remover da lista de reprodução",
@ -87,9 +89,9 @@
"clone_playlist_success": "Clonada com sucesso!",
"clone_playlist": "Clonar lista de reprodução",
"show_markers": "Mostrar marcas no reprodutor",
"delete_account": "Apagar conta",
"delete_account": "Eliminar conta",
"logout": "Terminar sessão neste dispositivo",
"minimize_recommendations_default": "Minimizar recomendações por omissão",
"minimize_recommendations_default": "Por definição, minimizar recomendações",
"invalidate_session": "Terminar sessão em todos os dispositivos",
"different_auth_instance": "Usar uma instância diferente para autenticação",
"instance_auth_selection": "Instância para autenticação",
@ -101,18 +103,18 @@
"piped_link": "Ligação do Piped",
"backup_preferences": "Exportar preferências",
"store_search_history": "Guardar histórico de pesquisas",
"hide_watched": "Ocultar do feed os vídeos visualizados",
"hide_watched": "Ocultar, do feed, os vídeos já vistos",
"documentation": "Documentação",
"status_page": "Estado",
"source_code": "Código-fonte",
"instance_donations": "Doações de instâncias",
"minimize_chapters_default": "Minimizar capítulos por omissão",
"minimize_chapters_default": "Por definição, minimizar capítulos",
"show_watch_on_youtube": "Mostrar botão Ver no YouTube",
"minimize_comments": "Minimizar comentários",
"back_to_home": "Voltar ao início",
"copy_link": "Copiar ligação",
"time_code": "Código de tempo (em segundos)",
"minimize_comments_default": "Minimizar comentários por omissão",
"minimize_comments_default": "Por definição, minimizar comentários",
"share": "Partilhar",
"with_timecode": "Partilhar com código de tempo",
"show_chapters": "Capítulos",
@ -137,13 +139,24 @@
"edit_playlist": "Editar lista de reprodução",
"playlist_name": "Nome da lista de reprodução",
"show_search_suggestions": "Mostrar sugestões de pesquisa",
"chapters_layout_mobile": "Aplicações recentemente adicionadas",
"enable_dearrow": "Ativar o DeArrow",
"chapters_layout_mobile": "Esquema de capítulos em dispositivos móveis",
"enable_dearrow": "Ativar DeArrow",
"delete_automatically": "Eliminar automaticamente após",
"generate_qrcode": "Gerar código QR",
"import_from_json_csv": "Importar de JSON/CSV",
"download_frame": "Quadro de transferência",
"instance_privacy_policy": "Política de privacidade"
"download_frame": "Descarregar moldura",
"instance_privacy_policy": "Política de privacidade",
"add_to_group": "Adicionar ao grupo",
"instances_not_shown": "As instâncias públicas que, atualmente, estejam indisponíveis, não serão mostradas aqui.",
"concurrent_prefetch_limit": "Limite de obtenção para fluxos simultâneos",
"customize": "Personalizar",
"invalid_url": "URL inválido!",
"add": "Adicionar",
"delete_group_confirm": "Eliminar este grupo?",
"creator_replied": "O criador respondeu",
"creator_liked": "O criador gostou",
"invalid_input": "Entrada inválida",
"playback_speed": "Velocidade de reprodução"
},
"preferences": {
"instance_name": "Nome da instância",
@ -152,13 +165,15 @@
"has_cdn": "Tem CDN?",
"version": "Versão",
"registered_users": "Utilizadores registados",
"up_to_date": "Atualizada?"
"up_to_date": "Atualizada?",
"uptime_30d": "Tempo de atividade (30d)",
"api_url": "URL da API"
},
"login": {
"password": "Palavra-passe",
"username": "Nome de utilizador",
"passwords_incorrect": "As palavras-passe não coincidem!",
"password_confirm": "Confirmar a palavra-passe"
"password_confirm": "Confirmar palavra-passe"
},
"video": {
"videos": "Vídeos",
@ -209,9 +224,11 @@
"preferences_note": "Nota: as preferências são guardadas no armazenamento local do seu navegador. Se limpar os dados de navegação, também limpa as preferências.",
"register_no_email_note": "Não recomendamos utilizar um endereço de e-mail como nome de utilizador. Continuar?",
"next_video_countdown": "O próximo vídeo será reproduzido dentro de {0} segundos",
"hours": "{quantidade} hora(s)",
"days": "{quantidade} dia(s)",
"weeks": "{quantidade} semana(s)",
"months": "{quantidade} mês(es)"
"hours": "{amount} hora(s)",
"days": "{amount} dia(s)",
"weeks": "{amount} semana(s)",
"months": "{amount} mês(es)",
"login_note": "Inicie sessão com uma conta criada nesta instância.",
"register_note": "Registe uma conta para esta instância Piped. Isso permitirá que sincronize as subscrições e listas de reprodução com a sua conta, para que elas sejam armazenadas nomo servidor. Pode usar todas as funções sem uma conta, mas todos os dados serão armazenados na cache do navegador. Certifique-se de que NÃO utiliza um endereço de e-mail como nome de utilizador e escolha uma palavra-passe segura."
}
}

View file

@ -1,138 +1,149 @@
{
"actions": {
"view_subscriptions": "Ver Inscrições",
"view_subscriptions": "Ver inscrições",
"back": "Voltar",
"most_recent": "Mais Recente",
"least_recent": "Menos Recente",
"most_recent": "Mais recentes",
"least_recent": "Mais antigos",
"sort_by": "Ordenar por:",
"channel_name_asc": "Nome do Canal (A-Z)",
"channel_name_desc": "Nome do Canal (Z-A)",
"channel_name_asc": "Nome do canal (A-Z)",
"channel_name_desc": "Nome do canal (Z-A)",
"dark": "Escuro",
"light": "Claro",
"show_comments": "Exibir Comentários",
"country_selection": "País",
"default_homepage": "Página Inicial Padrão",
"default_quality": "Qualidade Padrão",
"autoplay_video": "Reprodução Automática",
"minimize_description_default": "Minimizar Descrição por padrão",
"show_comments": "Mostrar comentários",
"country_selection": "Região",
"default_homepage": "Página inicial padrão",
"default_quality": "Qualidade padrão",
"autoplay_video": "Reprodução automática",
"minimize_description_default": "Ocultar descrição por padrão",
"theme": "Tema",
"audio_only": "Apenas Áudio",
"subscribe": "Inscrever-se - {count}",
"unsubscribe": "Desinscrever-se - {count}",
"skip_sponsors": "Pular Patrocinadores",
"audio_only": "Apenas áudio",
"subscribe": "Inscrever-se",
"unsubscribe": "Cancelar inscrição",
"skip_sponsors": "Pular patrocinadores",
"auto": "Automático",
"uses_api_from": "Usa a API de ",
"uses_api_from": "Usa a API ",
"enable_sponsorblock": "Ativar Sponsorblock",
"skip_interaction": "Pular Lembrete de Interação (Inscrever-se)",
"skip_self_promo": "Pular Promoção não paga/Autopromoção",
"show_markers": "Exibir Marcadores no Player",
"skip_intro": "Pular Intervalo/Introdução Animada",
"skip_outro": "Pular Créditos/Cartões finais",
"skip_preview": "Pular Pré-Visualização/Recapitulação",
"skip_highlight": "Pular Destaque",
"buffering_goal": "Cache de Buffer (em segundos)",
"skip_non_music": "Pular Música: Seção não Musical",
"skip_filler_tangent": "Pular Enchimento Tangencial",
"enabled_codecs": "Codecs Ativados (Múltiplos)",
"skip_interaction": "Pular lembrete de interação (inscrever-se)",
"skip_self_promo": "Pular autopromoção gratuita",
"show_markers": "Mostrar marcadores durante a reprodução",
"skip_intro": "Pular intervalo/animação de introdução",
"skip_outro": "Pular considerações/cartões finais",
"skip_preview": "Pular pré-visualização/recapitulação",
"skip_highlight": "Pular destaque",
"buffering_goal": "Meta de Buffer (em segundos)",
"skip_non_music": "Pular música: Partes sem relação com música",
"skip_filler_tangent": "Pular segmentos de preenchimento",
"enabled_codecs": "Codecs ativados (vários)",
"language_selection": "Idioma",
"yes": "Sim",
"show_more": "Mostrar Mais",
"export_to_json": "Exportar para JSON",
"donations": "Doações de desenvolvimento",
"minimize_recommendations": "Minimizar Recomendações",
"show_more": "Mostrar mais",
"export_to_json": "Exportar como JSON",
"donations": "Fazer doação para o desenvolvimento",
"minimize_recommendations": "Ocultar recomendações",
"loading": "Carregando...",
"hide_replies": "Ocultar Respostas",
"minimize_description": "Minimizar Descrição",
"load_more_replies": "Carregar mais Respostas",
"create_playlist": "Criar Playlist",
"delete_playlist": "Excluir Playlist",
"select_playlist": "Selecionar uma Playlist",
"hide_replies": "Ocultar respostas",
"minimize_description": "Ocultar descrição",
"load_more_replies": "Carregar mais respostas",
"create_playlist": "Criar playlist",
"delete_playlist": "Excluir playlist",
"select_playlist": "Escolha uma playlist",
"add_to_playlist": "Adicionar à playlist",
"delete_playlist_confirm": "Excluir esta playlist?",
"delete_playlist_video_confirm": "Remover vídeo da playlist?",
"please_select_playlist": "Por favor, selecione uma playlist",
"please_select_playlist": "Por favor, escolha uma playlist",
"remove_from_playlist": "Remover da playlist",
"view_ssl_score": "Ver Pontuação SSL",
"disable_lbry": "Desativar LBRY para Streaming",
"enable_lbry_proxy": "Ativar Proxy para LBRY",
"import_from_json": "Importar de JSON",
"loop_this_video": "Repetir este Vídeo",
"instances_list": "Lista de Instâncias",
"clear_history": "Limpar Histórico",
"view_ssl_score": "Ver pontuação SSL",
"disable_lbry": "Desativar LBRY para transmissões",
"enable_lbry_proxy": "Usar proxy em LBRY",
"import_from_json": "Importar arquivo JSON",
"loop_this_video": "Repetir este vídeo",
"instances_list": "Lista de instâncias",
"clear_history": "Limpar histórico",
"search": "Pesquisar (Ctrl+K)",
"no": "Não",
"show_description": "Exibir Descrição",
"show_description": "Mostrar descrição",
"instance_selection": "Instância",
"auto_play_next_video": "Autorreproduzir Próximo Vídeo",
"filter": "Filtro",
"store_watch_history": "Salvar Histórico de Exibição",
"show_recommendations": "Exibir Recomendações",
"minimize_comments_default": "Minimizar Comentários por padrão",
"minimize_comments": "Minimizar Comentários",
"different_auth_instance": "Use uma instância diferente para autenticação",
"delete_account": "Deletar Conta",
"auto_play_next_video": "Reproduzir próximo vídeo automaticamente",
"filter": "Filtrar",
"store_watch_history": "Salvar histórico de exibição",
"show_recommendations": "Mostrar recomendações",
"minimize_comments_default": "Ocultar comentários por padrão",
"minimize_comments": "Ocultar comentários",
"different_auth_instance": "Usar uma instância diferente para autenticação",
"delete_account": "Excluir conta",
"invalidate_session": "Sair de todos os dispositivos",
"clone_playlist": "Clonar Playlist",
"backup_preferences": "Fazer backup das preferências",
"clone_playlist": "Clonar playlist",
"backup_preferences": "Exportar preferências",
"logout": "Sair deste dispositivo",
"copy_link": "Copiar link",
"store_search_history": "Armazenar Histórico de Pesquisa",
"store_search_history": "Salvar histórico de pesquisa",
"hide_watched": "Ocultar vídeos assistidos no feed",
"status_page": "Estado",
"status_page": "Status",
"source_code": "Código fonte",
"instance_donations": "Doações de instâncias",
"instance_donations": "Fazer doação para instâncias",
"instance_privacy_policy": "Política de Privacidade",
"instance_auth_selection": "Instância de Autenticação",
"instance_auth_selection": "Instância para autenticação",
"clone_playlist_success": "Clonada com sucesso!",
"download_as_txt": "Baixar como .txt",
"restore_preferences": "Restaurar preferências",
"back_to_home": "Voltar ao início",
"back_to_home": "Ir para a página inicial",
"share": "Compartilhar",
"with_timecode": "Compartilhar com código de tempo",
"with_timecode": "Compartilhar no momento atual",
"piped_link": "Link do Piped",
"follow_link": "Seguir link",
"time_code": "Código de tempo (em segundos)",
"follow_link": "Abrir link",
"time_code": "Momento atual (em segundos)",
"show_chapters": "Capítulos",
"confirm_reset_preferences": "Tem certeza de que deseja redefinir suas preferências?",
"reset_preferences": "Redefinir preferências",
"documentation": "Documentação",
"reply_count": "{count} respostas",
"minimize_recommendations_default": "Minimizar Recomendações por padrão",
"show_watch_on_youtube": "Mostrar Botão Assistir no YouTube",
"minimize_chapters_default": "Minimizar Capítulos por padrão",
"reply_count": "{count} resposta(s)",
"minimize_recommendations_default": "Ocultar recomendações por padrão",
"show_watch_on_youtube": "Mostrar botão \"Assistir no YouTube\"",
"minimize_chapters_default": "Ocultar capítulos por padrão",
"no_valid_playlists": "O arquivo não contém playlists válidas!",
"with_playlist": "Compartilhar com playlist",
"with_playlist": "Compartilhar com a playlist",
"bookmark_playlist": "Favorito",
"playlist_bookmarked": "Favoritado",
"playlist_bookmarked": "Salvo como favorito",
"skip_automatically": "Automaticamente",
"skip_segment": "Ignorar Segmento",
"min_segment_length": "Comprimento Mínimo do Segmento (em segundos)",
"skip_button_only": "Mostrar botão pular",
"skip_segment": "Pular segmento",
"min_segment_length": "Comprimento mínimo do segmento (em segundos)",
"skip_button_only": "Mostrar botão \"Pular\"",
"show_less": "Mostrar menos",
"autoplay_next_countdown": "Contagem regressiva padrão até o próximo vídeo (em segundos)",
"dismiss": "Liberar",
"dismiss": "Dispensar",
"cancel": "Cancelar",
"edit_playlist": "Editar playlist",
"playlist_description": "Descrição da playlist",
"okay": "Ok",
"okay": "OK",
"playlist_name": "Nome da playlist",
"auto_display_captions": "Exibição Automática de Legendas",
"auto_display_captions": "Exibição automática de legendas",
"create_group": "Criar grupo",
"group_name": "Nome do grupo",
"show_search_suggestions": "Mostrar sugestões de pesquisa",
"chapters_layout_mobile": "Layout dos Capítulos no Celular",
"delete_automatically": "Deletar automaticamente após",
"generate_qrcode": "Gerar código QR",
"chapters_layout_mobile": "Layout de capítulos em dispositivos móveis",
"delete_automatically": "Excluir automaticamente após",
"generate_qrcode": "Código QR",
"enable_dearrow": "Ativar DeArrow",
"import_from_json_csv": "Importar de JSON/CSV",
"download_frame": "Baixar quadro"
"import_from_json_csv": "Importar arquivo JSON/CSV",
"download_frame": "Capturar imagem",
"add_to_group": "Adicionar ao grupo",
"instances_not_shown": "As instâncias públicas que não são mostradas aqui estão indisponíveis no momento.",
"concurrent_prefetch_limit": "Limite de pré-busca de fluxo simultâneo",
"customize": "Personalizar",
"invalid_url": "URL inválida!",
"add": "Adicionar",
"delete_group_confirm": "Excluir este grupo?",
"creator_replied": "O autor respondeu",
"creator_liked": "O autor gostou",
"playback_speed": "Velocidade de reprodução",
"invalid_input": "Entrada inválida"
},
"titles": {
"history": "Histórico",
"trending": "Em alta",
"preferences": "Preferências",
"register": "Registrar",
"login": "Entrar",
"register": "Criar conta",
"login": "Fazer login",
"playlists": "Playlists",
"feed": "Feed",
"subscriptions": "Inscrições",
@ -142,42 +153,46 @@
"channels": "Canais",
"livestreams": "Transmissões ao vivo",
"bookmarks": "Favoritos",
"channel_groups": "Grupos de Canais",
"dearrow": "DeArrow"
"channel_groups": "Grupos de canais",
"dearrow": "DeArrow",
"albums": "Álbuns",
"custom_instances": "Instâncias personalizadas"
},
"player": {
"watch_on": "Assistir no {0}",
"failed": "Falhou com código de erro {0}, veja os logs para mais informações"
"watch_on": "Ver em {0}",
"failed": "Falhou com código de erro {0}, consulte os logs para obter mais informações"
},
"comment": {
"pinned_by": "Fixado por {author}",
"user_disabled": "Os comentários estão desativados nas configurações.",
"disabled": "Os comentários são desativados pelo remetente.",
"disabled": "Os comentários foram desativados pelo autor.",
"loading": "Carregando comentários..."
},
"preferences": {
"registered_users": "Usuários Registrados",
"registered_users": "Usuários registrados",
"version": "Versão",
"instance_name": "Nome da Instância",
"instance_locations": "Localizações da Instância",
"instance_name": "Nome da instância",
"instance_locations": "Localizações da instância",
"has_cdn": "Tem CDN?",
"up_to_date": "Atualizado?",
"ssl_score": "Pontuação SSL"
"ssl_score": "Pontuação SSL",
"uptime_30d": "Tempo de atividade (30d)",
"api_url": "URL da Api"
},
"login": {
"username": "Nome de usuário",
"username": "Usuário",
"password": "Senha",
"password_confirm": "Confirme senha",
"passwords_incorrect": "As senhas não correspondem!"
"password_confirm": "Confirmar senha",
"passwords_incorrect": "As senhas não coincidem!"
},
"video": {
"videos": "Vídeos",
"views": "{views} visualizações",
"chapters": "Capítulos",
"live": "{0} Ao vivo",
"live": "{0} ao vivo",
"watched": "Assistido",
"ratings_disabled": "Avaliações Desativadas",
"sponsor_segments": "Segmentos de Patrocinadores",
"ratings_disabled": "Avaliações desativadas",
"sponsor_segments": "Segmentos patrocinados",
"shorts": "Shorts",
"all": "Todos",
"category": "Categoria",
@ -195,21 +210,23 @@
"music_videos": "YT Music: Vídeos",
"music_albums": "YT Music: Álbuns",
"music_playlists": "YT Music: Playlists",
"all": "YouTube: Tudo",
"all": "YouTube: Todos",
"music_artists": "YT Music: Artistas"
},
"info": {
"copied": "Copiado!",
"cannot_copy": "Não foi possível copiar!",
"preferences_note": "Nota: as preferências são salvas no armazenamento local do seu navegador. A exclusão dos dados do seu navegador irá redefini-los.",
"page_not_found": "página não encontrada",
"preferences_note": "Nota: as preferências são salvas no armazenamento local do seu navegador. Excluir os dados do seu navegador irá redefini-los.",
"page_not_found": "Página não encontrada",
"local_storage": "Esta ação requer localStorage, os cookies estão ativados?",
"register_no_email_note": "Usar um e-mail como nome de usuário não é recomendado. Continuar mesmo assim?",
"next_video_countdown": "Reproduzindo o próximo vídeo em {0}s",
"next_video_countdown": "Próximo vídeo em {0}s",
"hours": "{amount} hora(s)",
"days": "{amount} dia(s)",
"weeks": "{amount} semana(s)",
"months": "{amount} mês/meses"
"months": "{amount} mês(es)",
"login_note": "Faça login com uma conta registrada nesta instância.",
"register_note": "Registre uma conta para esta instância Piped. Isto irá permitir que você sincronize suas inscrições e playlists com sua conta, para que sejam armazenadas no lado do servidor. Você pode usar todas as funções sem uma conta, mas todos os dados serão armazenados no cache local do seu navegador. Por favor certifique-se de NÃO usar seu endereço de e-mail como nome de usuário e de escolher uma senha segura que não use em nenhum outro lugar."
},
"subscriptions": {
"subscribed_channels_count": "Inscrito em: {0}"

View file

@ -15,7 +15,9 @@
"channels": "Canais",
"bookmarks": "Marcadores",
"channel_groups": "Grupos de canais",
"dearrow": "DeArrow"
"dearrow": "DeArrow",
"albums": "Álbuns",
"custom_instances": "Instâncias personalizadas"
},
"actions": {
"view_subscriptions": "Ver subscrições",
@ -49,7 +51,7 @@
"enabled_codecs": "Codificadores ativados (vários)",
"instance_selection": "Instância",
"show_more": "Mostrar mais",
"import_from_json": "Importar de JSON/CSV",
"import_from_json": "Importar de JSON",
"loop_this_video": "Repetir este vídeo",
"auto_play_next_video": "Reproduzir vídeo seguinte automaticamente",
"donations": "Doações para o desenvolvimento",
@ -61,8 +63,8 @@
"search": "Pesquisa (Ctrl+K)",
"hide_replies": "Ocultar respostas",
"load_more_replies": "Carregar mais respostas",
"unsubscribe": "Anular subscrição - {count}",
"subscribe": "Subscrever - {count}",
"unsubscribe": "Anular subscrição",
"subscribe": "Subscrever",
"back": "Recuar",
"audio_only": "Apenas áudio",
"default_quality": "Qualidade padrão",
@ -139,7 +141,17 @@
"show_search_suggestions": "Mostrar sugestões de pesquisa",
"chapters_layout_mobile": "Aplicações recentemente adicionadas",
"enable_dearrow": "Ativar o DeArrow",
"delete_automatically": "Eliminar automaticamente após"
"delete_automatically": "Eliminar automaticamente após",
"generate_qrcode": "Gerar Código QR",
"add": "Adicionar",
"instance_privacy_policy": "Política de Privacidade",
"instances_not_shown": "Instâncias públicas que não aparecem aqui estão de momento em baixo.",
"import_from_json_csv": "Importar de JSON/CSV",
"download_frame": "Descarregar frame",
"add_to_group": "Adicionar a grupo",
"concurrent_prefetch_limit": "Limite de pré-busca de fluxo simultâneo",
"customize": "Personalizar",
"invalid_url": "URL inválido!"
},
"comment": {
"pinned_by": "Afixado por {author}",
@ -154,11 +166,15 @@
"registered_users": "Utilizadores registados",
"ssl_score": "Avaliação SSL",
"up_to_date": "Atualizada?",
"version": "Versão"
"version": "Versão",
"uptime_30d": "Tempo Online (30d)",
"api_url": "URL do API"
},
"login": {
"username": "Nome de utilizador",
"password": "Palavra-passe"
"password": "Palavra-passe",
"password_confirm": "Confirmar senha",
"passwords_incorrect": "Senhas não coincidem!"
},
"video": {
"videos": "Vídeos",
@ -189,7 +205,8 @@
"music_artists": "YT Music: Artistas"
},
"player": {
"watch_on": "Ver em {0}"
"watch_on": "Ver em {0}",
"failed": "Falha com o código de erro {0}, ver registos para mais informações"
},
"subscriptions": {
"subscribed_channels_count": "Subscreveu: {0}"
@ -205,6 +222,8 @@
"hours": "{quantidade} hora(s)",
"days": "{quantidade} dia(s)",
"weeks": "{quantidade} semana(s)",
"months": "{quantidade} mês(es)"
"months": "{quantidade} mês(es)",
"register_note": "Registar uma conta para esta instância de Piped. Isto ir-lhe-á permitir sincronizar as suas subscrições e playlists com a sua conta, então estarão guardadas no lado do servidor. Pode usar todas as funções sem uma conta, mas os seus dados serão guardados na cache local do seu browser. Por favor, certifique-se que você NÃO use um endereço de e-mail como o seu nome de utilizador e escolha uma palavra-passe forte que não use em mais nenhum lugar.",
"login_note": "Entre com uma conta criada nesta instância."
}
}

View file

@ -15,7 +15,7 @@
"delete_playlist_confirm": "Ștergeți acest playlist?",
"please_select_playlist": "Vă rugăm să alegeți un playlist",
"minimize_recommendations_default": "Minimizați recomandările în mod implicit",
"subscribe": "Abonare - {count}",
"subscribe": "Abonare",
"least_recent": "Cele mai vechi",
"channel_name_asc": "Numele canalului (A-Z)",
"channel_name_desc": "Nume canalului (Z-A)",
@ -73,7 +73,7 @@
"different_auth_instance": "Folosiți o instanță diferită pentru autentificare",
"clone_playlist": "Clonați lista de redare",
"backup_preferences": "Faceți backup la preferințe",
"unsubscribe": "Dezabonare - {count}",
"unsubscribe": "Dezabonare",
"view_subscriptions": "Vedeți abonamentele",
"sort_by": "Sortare după:",
"download_as_txt": "Descărcați ca .txt",
@ -93,7 +93,7 @@
"show_more": "Mai mult",
"no": "Nu",
"export_to_json": "Exportați ca JSON",
"import_from_json": "Importați din JSON/CSV",
"import_from_json": "Importați din JSON",
"auto_play_next_video": "Redați automat următorul video",
"minimize_recommendations": "Minimizați recomandările",
"yes": "Da",
@ -121,7 +121,18 @@
"chapters_layout_mobile": "Mod afișare capitole pe mobil",
"show_search_suggestions": "Afișare sugestii căutare",
"enable_dearrow": "Activați DeArrow",
"delete_automatically": "Șterge automat după"
"delete_automatically": "Șterge automat după",
"add_to_group": "Adăugați la grup",
"import_from_json_csv": "Importați din JSON/CSV",
"concurrent_prefetch_limit": "Limită de preluare anticipată a fluxului simultan",
"download_frame": "Descarcă cadrul",
"generate_qrcode": "Generează un cod QR",
"instance_privacy_policy": "Politica de confidențialitate",
"instances_not_shown": "Instanțele publice care nu sunt afișate aici nu sunt disponibile în prezent.",
"customize": "Customizează",
"invalid_url": "URL nevalid!",
"add": "Adăugați",
"delete_group_confirm": "Să șterg acest grup?"
},
"preferences": {
"ssl_score": "Scor SSL",
@ -130,7 +141,9 @@
"instance_name": "Nume instanță",
"instance_locations": "Locațiile instanței",
"has_cdn": "Are CDN?",
"registered_users": "Utilizatori înregistrați"
"registered_users": "Utilizatori înregistrați",
"uptime_30d": "Timp de funcționare (30 zile)",
"api_url": "URL-ul API"
},
"comment": {
"user_disabled": "Comentariile sunt dezactivate în setări.",
@ -150,11 +163,15 @@
"category": "Categorie",
"all": "Tot",
"chapters_horizontal": "Orizontal",
"chapters_vertical": "Vertical"
"chapters_vertical": "Vertical",
"visibility": "Vizibilitate",
"license": "Licență"
},
"login": {
"username": "Nume de utilizator",
"password": "Parolă"
"password": "Parolă",
"password_confirm": "Confirmați parola",
"passwords_incorrect": "Parolele nu se potrivesc!"
},
"search": {
"videos": "YouTube: Videoclipuri",
@ -176,7 +193,12 @@
"register_no_email_note": "Utilizarea unui e-mail ca nume de utilizator nu este recomandată. Continuați oricum?",
"local_storage": "Această acțiune necesită localStorage, sunt activate cookie-urile?",
"next_video_countdown": "Redarea următorului videoclip în {0}s",
"days": "{amount} zi(le)"
"days": "{amount} zi(le)",
"hours": "{amount} oră(e)",
"login_note": "Conectați-vă cu un cont creat în această instanță.",
"months": "{amount} lună(luni)",
"weeks": "{amount} săptămână(e)",
"register_note": "Înregistrați un cont pentru această instanță Piped. Acest lucru vă va permite să vă sincronizați abonamentele și listele de redare cu contul dvs., astfel încât acestea să fie stocate pe partea serverului. Puteți utiliza toate funcțiile fără un cont, dar toate datele vor fi stocate în memoria cache locală a browserului dvs. Vă rugăm să vă asigurați că NU folosiți o adresă de e-mail ca nume de utilizator și alegeți o parolă sigură pe care nu o folosiți în altă parte."
},
"subscriptions": {
"subscribed_channels_count": "Abonat la: {0}"
@ -197,9 +219,12 @@
"player": "Player-ul",
"bookmarks": "Marcaje",
"channel_groups": "Grupuri de canale",
"dearrow": "DeArrow"
"dearrow": "DeArrow",
"custom_instances": "Instanțe customizate",
"albums": "Albume"
},
"player": {
"watch_on": "Vizionați pe {0}"
"watch_on": "Vezi pe {0}",
"failed": "A eșuat cu codul de eroare {0}, consultați jurnalele pentru mai multe informații"
}
}

View file

@ -15,15 +15,17 @@
"channels": "Каналы",
"bookmarks": "Закладки",
"channel_groups": "Группы каналов",
"dearrow": "DeArrow"
"dearrow": "DeArrow",
"albums": "Альбомы",
"custom_instances": "Пользовательские серверы"
},
"player": {
"watch_on": "Смотреть на {0}",
"watch_on": "Посмотреть на {0}",
"failed": "Ошибка с кодом {0}, откройте логи, чтобы узнать больше"
},
"actions": {
"subscribe": "Подписаться - {count}",
"unsubscribe": "Отписаться - {count}",
"subscribe": "Подписаться",
"unsubscribe": "Отписаться",
"view_subscriptions": "Просмотреть подписки",
"sort_by": "Сортировка по:",
"most_recent": "Самые новые",
@ -41,7 +43,7 @@
"skip_self_promo": "Пропускать саморекламу",
"skip_non_music": "Пропускать тишину в музыкальных роликах",
"theme": "Тема",
"auto": "Автоматически",
"auto": "Авто",
"dark": "Тёмная",
"light": "Светлая",
"autoplay_video": "Автоматическое проигрывание видео",
@ -146,8 +148,19 @@
"enable_dearrow": "Включить DeArrow",
"generate_qrcode": "Сгенерировать QR Код",
"import_from_json_csv": "Импорт из JSON/CSV",
"download_frame": "Сделать скриншот видео",
"instance_privacy_policy": "Политика конфиденциальности"
"download_frame": "Скачать текущий кадр",
"instance_privacy_policy": "Политика конфиденциальности",
"add_to_group": "Добавить в группу",
"instances_not_shown": "Общедоступные экземпляры, которые здесь не показаны, в настоящее время недоступны.",
"concurrent_prefetch_limit": "Предел одновременной предзагрузки трансляций",
"customize": "Персонализация",
"invalid_url": "Неправильная ссылка!",
"add": "Добавить",
"creator_replied": "Ответ автора",
"creator_liked": "Автор оценил",
"playback_speed": "Скорость воспроизведения",
"invalid_input": "Некорректный ввод",
"delete_group_confirm": "Удалить группу?"
},
"comment": {
"pinned_by": "Закреплено пользователем {author}",
@ -162,7 +175,9 @@
"ssl_score": "Оценка настроек SSL",
"registered_users": "Зарегистрировано пользователей",
"version": "Версия",
"up_to_date": "Версия актуальна?"
"up_to_date": "Версия актуальна?",
"uptime_30d": "Доступность (30д)",
"api_url": "Ссылка API"
},
"login": {
"username": "Имя пользователя",
@ -212,6 +227,8 @@
"days": "{amount} дней",
"hours": "{amount} час(ов)",
"weeks": "{amount} недель",
"months": "{amount} месяцев"
"months": "{amount} месяцев",
"login_note": "Войти в аккаунт созданном на этом экземпляре.",
"register_note": "Зарегистрируйте учетную запись для данного экземпляра Piped. Это позволит синхронизировать подписки и списки воспроизведения с учетной записью, так что они будут храниться на стороне сервера. Вы можете использовать все функции без учетной записи, но все данные будут храниться в локальном кэше вашего браузера. Пожалуйста, убедитесь, что вы НЕ используете адрес электронной почты в качестве имени пользователя, и выберите надежный пароль, который вы не используете в других местах."
}
}

View file

@ -17,8 +17,8 @@
"channel_groups": "නාලිකා සමූහ"
},
"actions": {
"subscribe": "දායකවන්න - {count}",
"unsubscribe": "දායක නොවන්න - {count}",
"subscribe": "දායකවන්න",
"unsubscribe": "දායක නොවන්න",
"most_recent": "වඩාත් මෑත",
"least_recent": "ආසන්න මෑත",
"channel_name_asc": "නාලිකාවේ නම (අ-ෆ)",

View file

@ -1,62 +1,62 @@
{
"actions": {
"enable_lbry_proxy": "Povoliť Proxy pre LBRY",
"disable_lbry": "Vypnúť LBRY pre Živé Vysielania",
"enabled_codecs": "Povolené Kodeky (Viac)",
"instances_list": "Zoznam Inštancií",
"language_selection": "Výber Jazyka",
"store_watch_history": "Ukladať Históriu Pozerania",
"minimize_description_default": "Predvolene Zatvárať Popis",
"enable_lbry_proxy": "Povoliť proxy pre LBRY",
"disable_lbry": "Vypnúť LBRY pre živé vysielanie",
"enabled_codecs": "Povolené kodeky (viac)",
"instances_list": "Zoznam inštancií",
"language_selection": "Jazyk",
"store_watch_history": "Ukladať históriu pozerania",
"minimize_description_default": "Skryť popis predvolene",
"show_comments": "Zobraziť Komentáre",
"default_homepage": "Predvolená Domovská Stránka",
"country_selection": "Výber Krajiny",
"buffering_goal": "Cieľ Predtáčania (sekundy)",
"default_quality": "Predvolená Kvalita",
"audio_only": "Len Zvuk",
"autoplay_video": "Automaticky Prehrávať Video",
"default_homepage": "Úvodná stránka",
"country_selection": "Krajina",
"buffering_goal": "Vyrovnávacia pamäť (v sekundách)",
"default_quality": "Predvolená kvalita",
"audio_only": "Len zvuk",
"autoplay_video": "Automaticky prehrávať video",
"light": "Svetlá",
"dark": "Tmavá",
"auto": "Automaticky",
"theme": "Téma",
"skip_non_music": "Preskočiť Hudbu: Časť bez Hudby",
"skip_self_promo": "Preskočiť Neplatenú Reklamu/Vlastné Promo",
"skip_interaction": "Preskočiť Žiadosť o Interakciu (Odber)",
"skip_preview": "Preskočiť Náhľad/Prehľad",
"skip_outro": "Preskočiť Záverečné Obrazovky/Titulky",
"skip_intro": "Preskočiť Prestávku/Intro Animáciu",
"skip_sponsors": "Preskočiť Sponzorov",
"enable_sponsorblock": "Povoliť preskakovanie sponzorov",
"skip_non_music": "Vynechať hudbu: časť bez hudby",
"skip_self_promo": "Vynechať neplatenú/vlastnú propagáciu",
"skip_interaction": "Vynechať pripomenutie interakcie (prihlásenie k odberu)",
"skip_preview": "Vynechať náhľad/zhrnutie",
"skip_outro": "Vynechať koncové karty/titulky",
"skip_intro": "Vynechať prestávku/ úvodnú animáciu",
"skip_sponsors": "Vynechať sponzorov",
"enable_sponsorblock": "Povoliť SponsorBlock",
"uses_api_from": "Používa API z ",
"back": "Späť",
"channel_name_desc": "Meno kanálu (Z-A)",
"channel_name_asc": "Meno kanálu (A-Z)",
"channel_name_desc": "Názov kanála (Z-A)",
"channel_name_asc": "Názov kanála (A-Z)",
"least_recent": "Najstaršie",
"most_recent": "Najnovšie",
"sort_by": "Zoradiť podľa:",
"view_subscriptions": "Zobraziť odbery",
"unsubscribe": "Zrušiť odber - {count}",
"subscribe": "Odberať - {count}",
"minimize_recommendations": "Minimalizujte odporúčania",
"unsubscribe": "Zrušiť odber",
"subscribe": "Odoberať",
"minimize_recommendations": "Skryť odporúčania",
"show_recommendations": "Zobraziť odporúčania",
"export_to_json": "Exportovať do JSONu",
"skip_highlight": "Preskočiť Výstrižok",
"skip_filler_tangent": "Preskočiť Vyplnenie",
"instance_selection": "Výber inštancie",
"show_more": "Ukázať viac",
"export_to_json": "Exportovať do JSON",
"skip_highlight": "Vynechať highlight",
"skip_filler_tangent": "Vynechať súvisiaci obsah",
"instance_selection": "Inštancia",
"show_more": "Zobraziť viac",
"yes": "Áno",
"no": "Nie",
"import_from_json": "Importovať z JSON/CSVu",
"loop_this_video": "Opakovať",
"import_from_json": "Importovať z JSON",
"loop_this_video": "Opakovať video",
"auto_play_next_video": "Automaticky prehrávať ďalšie video",
"donations": "Dary",
"minimize_description": "Minimalizovať Popis",
"donations": "Príspevky na vývoj",
"minimize_description": "Skryť popis",
"clear_history": "Vymazať históriu",
"add_to_playlist": "Pridať do zoznamu skladieb",
"search": "Vyhľadávanie",
"add_to_playlist": "Pridať do playlistu",
"search": "Hľadať (Ctrl+K)",
"show_chapters": "Kapitoly",
"create_playlist": "Vytvoriť zoznam skladieb",
"select_playlist": "Vyberte zoznam skladieb",
"please_select_playlist": "Prosím, vyberte zoznam skladieb",
"create_playlist": "Vytvoriť playlist",
"select_playlist": "Vybrať playlist",
"please_select_playlist": "Vyberte zoznam skladieb",
"back_to_home": "Späť domov",
"copy_link": "Skopírovať odkaz",
"time_code": "Časový kód (v sekundách)",
@ -64,33 +64,83 @@
"piped_link": "Piped odkaz",
"show_markers": "Zobraziť značky na prehrávači",
"hide_replies": "Skryť odpovede",
"delete_playlist": "Odstrániť zoznam skladieb",
"delete_playlist_confirm": "Odstrániť tento zoznam skladieb?",
"remove_from_playlist": "Odstrániť zo zoznamu skladieb",
"delete_playlist": "Vymazať playlist",
"delete_playlist_confirm": "Vymazať tento playlist?",
"remove_from_playlist": "Odstrániť z playlistu",
"load_more_replies": "Načítať viac odpovedí",
"show_description": "Zobraziť popis",
"view_ssl_score": "Zobraziť SSL skóre",
"filter": "Filter",
"delete_playlist_video_confirm": "Odstrániť video zo zoznamu?",
"view_ssl_score": "Zobraziť skóre SSL",
"filter": "Filtrovať",
"delete_playlist_video_confirm": "Odstrániť video z playlistu?",
"share": "Zdieľať",
"follow_link": "Nasledujte odkaz",
"follow_link": "Otvoriť odkaz",
"loading": "Načítavanie...",
"download_as_txt": "Stiahnuť ako .txt",
"reset_preferences": "Resetovať preferencie",
"confirm_reset_preferences": "Naozaj chcete resetovať svoje preferencie?",
"backup_preferences": "Zálohovať preferencie",
"restore_preferences": "Obnoviť preferencie",
"delete_account": "Zmazať účet",
"logout": "Odhlásiť z tohto zariadenia",
"minimize_recommendations_default": "Minimalizovať odporúčania predvolene",
"reset_preferences": "Resetovať nastavenia",
"confirm_reset_preferences": "Naozaj chcete resetovať svoje nastavenia?",
"backup_preferences": "Zálohovať nastavenia",
"restore_preferences": "Obnoviť nastavenia",
"delete_account": "Vymazať účet",
"logout": "Odhlásiť sa z tohto zariadenia",
"minimize_recommendations_default": "Skryť odporúčania predvolene",
"different_auth_instance": "Na overenie použite inú inštanciu",
"instance_auth_selection": "Výber inštancie autentifikácie",
"invalidate_session": "Odhláste sa zo všetkých zariadení",
"clone_playlist": "Klonovať zoznam skladieb",
"clone_playlist_success": "Úspešne klonované!"
"instance_auth_selection": "Autentifikačná inštancia",
"invalidate_session": "Odhlásiť sa zo všetkých zariadení",
"clone_playlist": "Klonovať playlist",
"clone_playlist_success": "Úspešne klonované!",
"skip_button_only": "Zobraziť tlačidlo preskočenia",
"skip_automatically": "Automaticky",
"min_segment_length": "Minimálna dĺžka segmentu (v sekundách)",
"skip_segment": "Vynechať segment",
"autoplay_next_countdown": "Predvolené odpočítavanie do nasledujúceho videa (v sekundách)",
"show_watch_on_youtube": "Zobraziť tlačidlo Pozerať na YouTube",
"minimize_comments_default": "Skryť komentáre predvolene",
"edit_playlist": "Upraviť playlist",
"instances_not_shown": "Verejné inštancie, ktoré tu nie sú zobrazené, sú momentálne nedostupné.",
"enable_dearrow": "Povoliť DeArrow",
"import_from_json_csv": "Importovať z JSON/CSV",
"auto_display_captions": "Automatické zobrazovanie titulkov",
"minimize_comments": "Skryť komentáre",
"minimize_chapters_default": "Skryť kapitoly predvolene",
"chapters_layout_mobile": "Rozloženie kapitol v mobile",
"playlist_name": "Názov playlistu",
"dismiss": "Odmietnuť",
"playlist_bookmarked": "Záložka pridaná",
"show_less": "Zobraziť menej",
"documentation": "Dokumentácia",
"reply_count": "{count} odpovedí",
"concurrent_prefetch_limit": "Limit súbežného prednačítania streamu",
"status_page": "Stav",
"with_playlist": "Zdieľať s playlistom",
"create_group": "Vytvoriť skupinu",
"cancel": "Zrušiť",
"bookmark_playlist": "Pridať záložku",
"group_name": "Názov skupiny",
"playlist_description": "Popis playlistu",
"store_search_history": "Ukladať históriu hľadania",
"hide_watched": "Skryť pozerané videá v kanáli",
"source_code": "Zdrojový kód",
"instance_donations": "Príspevky na inštanciu",
"no_valid_playlists": "Súbor neobsahuje platné playlisty!",
"okay": "Dobre",
"show_search_suggestions": "Zobraziť návrhy vyhľadávania",
"delete_automatically": "Vymazať automaticky po",
"download_frame": "Stiahnuť snímok",
"add_to_group": "Pridať do skupiny",
"instance_privacy_policy": "Zásady ochrany osobných údajov",
"generate_qrcode": "Vygenerovať QR kód",
"customize": "Prispôsobiť",
"invalid_url": "Neplatná adresa URL!",
"add": "Pridať",
"delete_group_confirm": "Vymazať túto skupinu?",
"creator_replied": "Odpoveď autora",
"creator_liked": "Autorovi sa páčilo",
"invalid_input": "Nesprávne údaje",
"playback_speed": "Rýchlosť prehrávania"
},
"player": {
"watch_on": "Pozerať na {0}"
"watch_on": "Zobraziť na {0}",
"failed": "Zlyhalo s chybovým kódom {0}, viac informácií nájdete v protokole"
},
"titles": {
"history": "História",
@ -103,55 +153,82 @@
"playlists": "Playlisty",
"account": "Účet",
"instance": "Inštancia",
"player": "Prehrávač"
"player": "Prehrávač",
"livestreams": "Živé vysielania",
"bookmarks": "Záložky",
"channels": "Kanály",
"dearrow": "DeArrow",
"channel_groups": "Skupiny kanálov",
"albums": "Albumy",
"custom_instances": "Vlastné inštancie"
},
"preferences": {
"up_to_date": "Aktuálny?",
"ssl_score": "SSL skóre",
"up_to_date": "Aktuálna?",
"ssl_score": "Skóre SSL",
"instance_name": "Názov inštancie",
"instance_locations": "Miesto inštancií",
"registered_users": "Registrovaní užívatelia",
"has_cdn": "Má CDN?",
"version": "Verzia"
"instance_locations": "Umiestnenia inštancií",
"registered_users": "Registrovaní používatelia",
"has_cdn": "Používa sieť CDN?",
"version": "Verzia",
"uptime_30d": "Doba prevádzky (30 dní)",
"api_url": "Api URL"
},
"video": {
"sponsor_segments": "Sponzorské segmenty",
"ratings_disabled": "Hodnotenia sú vypnuté",
"ratings_disabled": "Hodnotenia sú zakázané",
"chapters": "Kapitoly",
"videos": "Videá",
"views": "{views} zhliadnutí",
"live": "{0} Live",
"views": "{views} zobrazení",
"live": "{0} Naživo",
"shorts": "Shorts",
"watched": "Zhliadnuté"
"watched": "Pozerané",
"license": "Licencia",
"visibility": "Viditeľnosť",
"chapters_horizontal": "Horizontálne",
"category": "Kategória",
"all": "Všetko",
"chapters_vertical": "Vertikálne"
},
"search": {
"did_you_mean": "Mali ste na mysli: {0}?",
"channels": "YouTube: Kanály",
"playlists": "YouTube: Zoznamy skladieb",
"music_playlists": "YT Music: Zoznamy skladieb",
"playlists": "YouTube: Playlisty",
"music_playlists": "YT Music: Playlisty",
"music_songs": "YT Music: Piesne",
"music_videos": "YT Music: Videá",
"music_albums": "YT Music: Albumy",
"all": "YouTube: Všetko",
"videos": "YouTube: Videá"
"videos": "YouTube: Videá",
"music_artists": "YT Music: Umelci"
},
"info": {
"preferences_note": "Poznámka: preferencie sú uložené v miestnom úložisku vášho prehliadača. Odstránením údajov prehliadača ich resetujete.",
"page_not_found": "Stránka nenájdená",
"preferences_note": "Poznámka: predvoľby sa ukladajú do miestnej pamäte prehliadača. Vymazaním údajov prehliadača sa resetujú.",
"page_not_found": "Stránka nebola nájdená",
"copied": "Skopírované!",
"cannot_copy": "Nedá sa kopírovať!"
"cannot_copy": "Nedá sa kopírovať!",
"next_video_countdown": "Ďalšie video sa prehrá o {0} sekúnd",
"days": "{amount} d.",
"weeks": "{amount} týžd.",
"months": "{amount} mes.",
"login_note": "Prihláste sa pomocou účtu vytvoreného na tejto inštancii.",
"local_storage": "Táto akcia vyžaduje lokálne úložisko, sú povolené súbory cookie?",
"register_no_email_note": "Použitie e-mailu ako používateľského mena sa neodporúča. Napriek tomu pokračovať?",
"hours": "{amount} hod.",
"register_note": "Zaregistrujte si účet pre túto inštanciu Piped. Umožní vám to synchronizovať odbery a playlisty s vaším účtom, takže budú uložené na strane servera. Všetky funkcie môžete používať bez účtu, ale všetky údaje budú uložené v lokálnej vyrovnávacej pamäti prehliadača. Uistite sa, že NEPOUŽÍVATE e-mailovú adresu ako svoje používateľské meno a zvoľte si bezpečné heslo, ktoré inde nepoužívate."
},
"subscriptions": {
"subscribed_channels_count": "Odoberať: {0}"
"subscribed_channels_count": "Odobera: {0}"
},
"login": {
"username": "Užívatelksé meno",
"password": "Heslo"
"username": "Používateľské meno",
"password": "Heslo",
"password_confirm": "Potvrdiť heslo",
"passwords_incorrect": "Heslo je nesprávne!"
},
"comment": {
"loading": "Načítavajú sa komentáre...",
"disabled": "Komentáre sú vypnuté používateľom, ktorý nahral video.",
"loading": "Načítavanie komentárov...",
"disabled": "Komentáre sú zakázané používateľom, ktorý nahral video.",
"user_disabled": "Komentáre sú v nastaveniach zakázané.",
"pinned_by": "Pripnuté {author}"
"pinned_by": "Pripnuté používateľom {author}"
}
}

224
src/locales/sl.json Normal file
View file

@ -0,0 +1,224 @@
{
"video": {
"sponsor_segments": "Segmenti sponzorjev",
"watched": "Ogledano",
"views": "{views} ogledov",
"videos": "Videoposnetki",
"ratings_disabled": "Ocene so izklopljene",
"chapters": "Poglavja",
"live": "{0} v živo",
"shorts": "Kratki videoposnetki",
"all": "Vse",
"category": "Kategorija",
"chapters_horizontal": "Vodoravno",
"chapters_vertical": "Navpično",
"license": "Licenca",
"visibility": "Vidnost"
},
"preferences": {
"ssl_score": "SSL ocena",
"has_cdn": "Ima CDN?",
"instance_locations": "Lokacije instanc",
"instance_name": "Ime instance",
"registered_users": "Registrirani uporabniki",
"version": "Različica",
"up_to_date": "Najnovejša različica?"
},
"comment": {
"pinned_by": "Pripel uporabnik {author}",
"disabled": "Komentiranje je izklopljeno.",
"loading": "Nalaganje komentarjev...",
"user_disabled": "Komentarji so izklopljeni v nastavitvah."
},
"actions": {
"enable_lbry_proxy": "Vklopi proxy za LBRY",
"disable_lbry": "Izklopi LBRY za prenos",
"minimize_description_default": "Privzeto skrij opis",
"minimize_description": "Skrij opis",
"show_description": "Prikaži opis",
"minimize_recommendations": "Skrij priporočila",
"show_recommendations": "Prikaži priporočila",
"donations": "Donacije za razvoj",
"auto_play_next_video": "Samodejno predvajaj naslednji videoposnetek",
"loop_this_video": "Ponavljaj ta videoposnetek",
"import_from_json": "Uvozi iz formata JSON",
"export_to_json": "Izvozi v format JSON",
"no": "Ne",
"yes": "Da",
"show_more": "Prikaži več",
"instance_selection": "Instanca",
"enabled_codecs": "Vklopljeni kodeki (možno je izbrati več kodekov)",
"instances_list": "Seznam instanc",
"language_selection": "Jezik",
"store_watch_history": "Shrani zgodovino ogledov",
"show_comments": "Prikaži komentarje",
"default_homepage": "Privzeta domača stran",
"country_selection": "Država",
"buffering_goal": "Cilj medpomnilnika (v sekundah)",
"default_quality": "Privzeta kakovost",
"audio_only": "Samo zvok",
"autoplay_video": "Samodejno predvajaj videoposnetek",
"light": "Svetla",
"dark": "Temna",
"auto": "Samodejna",
"theme": "Tema",
"skip_non_music": "Preskoči dele brez glasbe",
"skip_self_promo": "Preskoči neplačane oglase ali osebne promocije",
"skip_preview": "Preskoči predogled/povzetek",
"uses_api_from": "Uporabi API od ",
"back": "Nazaj",
"channel_name_desc": "Ime kanala (ZA)",
"channel_name_asc": "Ime kanala (AZ)",
"least_recent": "Najprej najstarejši",
"most_recent": "Najprej najnovejši",
"sort_by": "Razvrsti glede na:",
"view_subscriptions": "Oglej si naročnine",
"unsubscribe": "Odjava {count}",
"subscribe": "Naroči se {count}",
"skip_interaction": "Preskoči opomnik za interakcijo (naročnina)",
"skip_outro": "Preskoči odjavno animacijo",
"skip_intro": "Preskoči uvodno animacijo",
"skip_sponsors": "Preskoči sponzorje",
"enable_sponsorblock": "Vklopi blok sponzorjev",
"loading": "Nalaganje…",
"filter": "Filter",
"search": "Iskanje (Ctrl+K)",
"view_ssl_score": "Poglej oceno SSL",
"hide_replies": "Skrij odgovore",
"load_more_replies": "Prikaži več odgovorov",
"clear_history": "Izbriši zgodovino",
"skip_highlight": "Preskoči poudarke",
"skip_filler_tangent": "Preskoči prazne vložke",
"delete_playlist_confirm": "Izbrišem ta seznam predvajanja?",
"remove_from_playlist": "Odstrani s seznama predvajanja",
"create_playlist": "Ustvari seznam predvajanja",
"delete_playlist": "Izbriši seznam predvajanja",
"add_to_playlist": "Dodaj na seznam predvajanja",
"select_playlist": "Izberi seznam predvajanja",
"please_select_playlist": "Izberi seznam predvajanja",
"delete_playlist_video_confirm": "Odstranim videoposnetek s seznama predvajanja?",
"show_markers": "Prikaži oznake na predvajalniku",
"delete_account": "Izbriši račun",
"logout": "Odjavi se iz te naprave",
"minimize_recommendations_default": "Privzeto skrij priporočila",
"invalidate_session": "Odjavi vse naprave",
"different_auth_instance": "Za preverjanje pristnosti uporabi drugo instanco",
"instance_auth_selection": "Instanca preverjanja pristnosti",
"clone_playlist": "Podvoji seznam predvajanja",
"clone_playlist_success": "Podvojitev je uspela!",
"download_as_txt": "Prenesi kot .txt",
"reset_preferences": "Ponastavi nastavitve",
"piped_link": "Cevna povezava",
"follow_link": "Sledi povezavi",
"copy_link": "Kopiraj povezavo",
"time_code": "Časovna koda (v sekundah)",
"restore_preferences": "Obnovi nastavitve",
"back_to_home": "Nazaj na domačo stran",
"confirm_reset_preferences": "Res želiš ponastaviti svoje nastavitve?",
"backup_preferences": "Varnostno kopiraj svoje nastavitve",
"with_timecode": "Deli s časovno kodo",
"share": "Deli",
"show_chapters": "Poglavja",
"documentation": "Dokumentacija",
"source_code": "Izvorna koda",
"instance_donations": "Donacije instanc",
"store_search_history": "Shranjevanje zgodovine iskanja",
"hide_watched": "Skrij ogledane videoposnetke v viru novic",
"status_page": "Stanje",
"reply_count": "{count} odgovorov",
"minimize_comments_default": "Privzeto skrij komentarje",
"minimize_comments": "Skrij komentarje",
"show_watch_on_youtube": "Prikaži gumb „Ogled v YouTubu”",
"minimize_chapters_default": "Privzeto skrij poglavja",
"no_valid_playlists": "Datoteka ne vsebuje veljavnih seznamov predvajanja!",
"with_playlist": "Deli s seznamom predvajanja",
"playlist_bookmarked": "Dodano",
"bookmark_playlist": "Dodaj",
"skip_button_only": "Pokaži gumb za preskok",
"skip_automatically": "Samodejno",
"skip_segment": "Preskoči segment",
"min_segment_length": "Najmanjša dolžina segmenta (v sekundah)",
"show_less": "Prikaži manj",
"autoplay_next_countdown": "Privzeto odštevanje do naslednjega videa (v sekundah)",
"dismiss": "Zavrzi",
"create_group": "Ustvari skupino",
"group_name": "Ime skupine",
"auto_display_captions": "Samodejno prikaži podnapise",
"cancel": "Prekliči",
"okay": "V redu",
"edit_playlist": "Uredi seznam predvajanja",
"playlist_name": "Ime seznama predvajanja",
"playlist_description": "Opis seznama predvajanja",
"chapters_layout_mobile": "Postavitev poglavij na mobilnih napravah",
"show_search_suggestions": "Pokaži predloge za iskanje",
"delete_automatically": "Samodejno izbriši po",
"enable_dearrow": "Vklopi DeArrow",
"generate_qrcode": "Ustvari kodo QR",
"import_from_json_csv": "Uvozi iz formata JSON/CSV",
"download_frame": "Prenesi okvir",
"instance_privacy_policy": "Politika zasebnosti",
"add_to_group": "Dodaj skupini",
"instances_not_shown": "Javne instance, ki tukaj niso prikazane, trenutno niso na voljo."
},
"player": {
"watch_on": "Glej na {0}",
"failed": "Ni uspelo z napako {0}. Za več informacij si oglej dnevnik"
},
"titles": {
"subscriptions": "Naročnine",
"history": "Zgodovina",
"preferences": "Nastavitve",
"feed": "Novosti",
"register": "Registracija",
"login": "Prijava",
"trending": "V trendu",
"playlists": "Seznami predvajanja",
"account": "Račun",
"instance": "Instanca",
"player": "Predvajalnik",
"channels": "Kanali",
"livestreams": "Prenosi v živo",
"bookmarks": "Opombe",
"channel_groups": "Skupine kanalov",
"dearrow": "DeArrow"
},
"login": {
"password": "Geslo",
"username": "Uporabniško ime",
"password_confirm": "Potrdi geslo",
"passwords_incorrect": "Geslo se ne ujema!"
},
"search": {
"did_you_mean": "Ali misliš: {0}?",
"all": "YouTube: Vse",
"videos": "YouTube: Videoposnetki",
"channels": "YouTube: Kanali",
"playlists": "YouTube: Seznami predvajanja",
"music_songs": "YouTube Music: Pesmi",
"music_videos": "YouTube Music: Videoposnetki",
"music_albums": "YouTube Music: Albumi",
"music_playlists": "YouTube Music: Seznami predvajanja",
"music_artists": "YouTube Music: Izvajalci"
},
"subscriptions": {
"subscribed_channels_count": "Število naročnin: {0}"
},
"information": {
"preferences_note": "Opomba: nastavitve so shranjene v lokalni shrambi brskalnika. Brisanje podatkov brskalnika ponastavi nastavitve."
},
"info": {
"preferences_note": "Opomba: nastavitve so shranjene v lokalni shrambi brskalnika. Pri izbrisu podatkov bo brskalnik ponastavljen.",
"page_not_found": "Stran ni najdena",
"copied": "Kopirano!",
"cannot_copy": "Ni mogoče kopirati!",
"local_storage": "Za to dejanje je potreben lokalni repozitorij. So piškotki vključeni?",
"register_no_email_note": "Uporaba e-poštnega naslova kot uporabniškega imena ni priporočljiva. Vseeno nadaljujem?",
"next_video_countdown": "Predvajanje naslednjega videa čez {0} s",
"hours": "{amount} ur",
"days": "{amount} dni",
"weeks": "{amount} ted.",
"months": "{amount} mes.",
"login_note": "Prijavite se z računom, ustvarjenim v tej instanci.",
"register_note": "Registrirajte račun za Piped. To vam bo omogočilo sinhronizacijo vaših naročnin in seznamov predvajanja z vašim računom, da bodo shranjeni na strežniku. Vse funkcije lahko uporabljate tudi brez računa, vendar bodo vsi podatki shranjeni v lokalnem pomnilniku vašega brskalnika. NE uporabljajte svojega e-poštnega naslova kot uporabniškega imena in izberite varno geslo, ki ga ne uporabljate drugje."
}
}

View file

@ -1,187 +1,234 @@
{
"video": {
"videos": "Видео клипови",
"watched": "Погледано",
"sponsor_segments": "Број делова видеа са спонзорима",
"views": "{views} приказа",
"videos": "Видео снимци",
"watched": "Одгледано",
"sponsor_segments": "Спонзор сегменти",
"views": "{views} прегледа",
"ratings_disabled": "Оцене су онемогућене",
"chapters": "Поглавља",
"live": "{0} Уживо",
"shorts": "Кратки видео снимци",
"shorts": "Shorts",
"all": "Све",
"category": "Категорија"
"category": "Категорија",
"visibility": "Видљивост",
"license": "Лиценца",
"chapters_vertical": "Вертикално",
"chapters_horizontal": "Хоризонтално"
},
"actions": {
"view_ssl_score": "Погледај SSL скор/оцену",
"view_ssl_score": "Погледај SSL оцену",
"loading": "Учитавање...",
"filter": "Филтер",
"hide_replies": "Сакриј одговоре",
"channel_name_asc": "Име канала (A-Z)",
"channel_name_desc": "Име канала (Z-A)",
"skip_self_promo": "Прескочи неплаћене промоције или самопромоције",
"minimize_description_default": "Смањи опис видеа (подразумевано)",
"enabled_codecs": "Омогућени видео кодеци (више)",
"instance_selection": збор инстанце",
"load_more_replies": "Учитај још одговора",
"unsubscribe": "Прекини са праћењем - {count}",
"channel_name_asc": "Име канала (А)",
"channel_name_desc": "Име канала (Ш-А)",
"skip_self_promo": "Прескочи неплаћене промоције/самопромоције",
"minimize_description_default": "Подразумевано минимизирај опис",
"enabled_codecs": "Омогућени кодеци (више)",
"instance_selection": нстанца",
"load_more_replies": "Учитај више одговора",
"unsubscribe": "Прекини праћење",
"auto": "Аутоматски",
"search": "Претрага (Ctrl+K)",
"skip_non_music": "Прескочи делове где нема музике у музичким видео клиповима",
"theme": "Теме",
"skip_non_music": "Прескочи музику: сегмент без музике",
"theme": "Тема",
"audio_only": "Само звук",
"show_description": "Прикажи опис",
"subscribe": "Прати - {count}",
"default_quality": "Подразумевани квалитет видеа",
"clear_history": "Обриши повест гледања",
"sort_by": "Сортирај по:",
"view_subscriptions": рикажи праћења",
"most_recent": "Најновији",
"least_recent": "Недавно",
"uses_api_from": "Корсти API од: ",
"enable_sponsorblock": "Омогући блокирање спонзора (Sponsorblock)",
"subscribe": "Запрати",
"default_quality": "Подразумевани квалитет",
"clear_history": "Очисти историју гледања",
"sort_by": "Сортирање по:",
"view_subscriptions": огледај праћења",
"most_recent": "Најновије",
"least_recent": "Најстарије",
"uses_api_from": "Користи API од: ",
"enable_sponsorblock": "Омогући SponsorBlock",
"skip_sponsors": "Прескочи спонзоре",
"skip_intro": "Прескочи уводне шпице/анимације",
"skip_intro": "Прескочи паузу/уводну анимацију",
"back": "Назад",
"skip_outro": "Прескочи картице на крају видеа",
"skip_preview": "Прескочи преглед/рикеп",
"skip_interaction": "Прескочи подсетнике за интеракије и пријаве (када неко позове да се претплатите или лајкујете)",
"skip_outro": "Прескочи завршне картице/кредите",
"skip_preview": "Прескочи преглед/рекапитулацију",
"skip_interaction": "Прескочи подсетник за интеракцију (праћење)",
"light": "Светла",
"autoplay_video": "Аутоматски пусти видео",
"buffering_goal": "Задато време баферовања (у секундама) (докле видео треба да се баферује пре почетка)",
"autoplay_video": "Аутоматски пусти видео снимак",
"buffering_goal": "Циљ баферовања (у секундама)",
"dark": "Тамна",
"country_selection": "Избор земаља",
"country_selection": "Држава",
"show_comments": "Прикажи коментаре",
"default_homepage": "Подразумевана почетна страна",
"instances_list": "Листе инстанци",
"store_watch_history": "Спреми повест гледања",
"language_selection": "Избор језика",
"default_homepage": "Подразумевана почетна страница",
"instances_list": "Листа инстанци",
"store_watch_history": "Чувај историју гледања",
"language_selection": "Језик",
"show_more": "Прикажи више",
"yes": "Да",
"export_to_json": "Извези у JSON",
"import_from_json": "Увези из JSON/CSV-а",
"minimize_recommendations": "Смањи препоруке",
"import_from_json": "Увези из JSON-а",
"minimize_recommendations": "Минимизирај препоруке",
"disable_lbry": "Онемогући LBRY за стримовање",
"enable_lbry_proxy": "Омогући прокси за LBRY",
"no": "Не",
"loop_this_video": уштај видео изнова (бесконачно)",
"auto_play_next_video": "Аутоматски пусти следећи видео",
"loop_this_video": онављај овај видео снимак",
"auto_play_next_video": "Аутоматски пусти следећи видео снимак",
"donations": "Донације за развој",
"minimize_description": "Сакриј опис",
"minimize_description": "Минимизирај опис",
"show_recommendations": "Прикажи препоруке",
"skip_highlight": "Прескочи истицање",
"skip_filler_tangent": "Прескочи небитне уметке",
"remove_from_playlist": "Уклони из пописа снимака",
"delete_playlist_video_confirm": "Да ли желите да уклоните видео из пописа снимака?",
"create_playlist": "Направите попис снимака",
"select_playlist": "Одаберите попис снимака",
"delete_playlist": "Избришите попис снимака",
"add_to_playlist": "Додај у попис снимака",
"delete_playlist_confirm": "Избрисати овај попис снимака?",
"please_select_playlist": "Молим вас одаберите попис снимака",
"show_markers": "Прикажи обиљеживаче на покретнику",
"delete_account": "Обриши налог",
"skip_highlight": "Прескочи истакнуто",
"skip_filler_tangent": "Прескочи попуњавање (неповезане сцене)",
"remove_from_playlist": "Уклони са плејлисте",
"delete_playlist_video_confirm": "Уклонити видео снимак са плејлисте?",
"create_playlist": "Направи плејлисту",
"select_playlist": "Избор плејлисте",
"delete_playlist": "Избриши плејлисту",
"add_to_playlist": "Додај на плејлисту",
"delete_playlist_confirm": "Избрисати ову плејлисту?",
"please_select_playlist": "Молимо, изаберите плејлисту",
"show_markers": "Прикажи маркере на плејеру",
"delete_account": "Избриши налог",
"logout": "Одјава са овог уређаја",
"minimize_recommendations_default": "Умањи Препоруке као Подразумевано",
"download_as_txt": "Преузмите као .ткт",
"reset_preferences": "Ресетирајте преференције",
"confirm_reset_preferences": "Да ли сте сигурни да желите да ресетујете подешавања?",
"backup_preferences": "Спреми сигурносну копију поставки",
"invalidate_session": "Одјавите се са свих уређаја",
"different_auth_instance": "Користите другу инстанцу за аутентификацију",
"instance_auth_selection": збор инстанце аутентикације",
"clone_playlist": "Клонирајте листу за репродукцију",
"minimize_recommendations_default": "Подразумевано минимизирај препоруке",
"download_as_txt": "Преузми као .txt",
"reset_preferences": "Ресетуј подешавања",
"confirm_reset_preferences": "Желите ли заиста да ресетујете подешавања?",
"backup_preferences": "Направи резервну копију подешавања",
"invalidate_session": "Одјава са свих уређаја",
"different_auth_instance": "Користи другу инстанцу за аутентификацију",
"instance_auth_selection": нстанца аутентификације",
"clone_playlist": "Клонирај плејлисту",
"clone_playlist_success": "Успешно клонирано!",
"share": "Подели",
"restore_preferences": "Врати поставке",
"source_code": "Изворни код",
"store_search_history": "Чувај историје претраге",
"hide_watched": "Сакриј гледане видео записе у фиду",
"share": "Дели",
"restore_preferences": "Врати подешавања",
"source_code": "Изворни кôд",
"store_search_history": "Чувај историју претраге",
"hide_watched": "Сакриј одгледане видео снимке у фиду",
"documentation": "Документација",
"status_page": "Статус",
"instance_donations": "Донације инстанци",
"show_chapters": "Поглавља",
"with_timecode": "Подели са временским кодом",
"piped_link": "Piped веза",
"back_to_home": "Врати се на почетну",
"follow_link": "Прати везу",
"copy_link": "Копирај везу",
"time_code": "Временски код (у секундама)",
"minimize_comments_default": "Подразумевано умањи коментаре",
"minimize_comments": "Умањи коментаре",
"with_timecode": "Дели са временским кодом",
"piped_link": "Piped линк",
"back_to_home": "Назад на почетну",
"follow_link": "Прати линк",
"copy_link": "Копирај линк",
"time_code": "Временски кôд (у секундама)",
"minimize_comments_default": "Подразумевано минимизирај коментаре",
"minimize_comments": "Минимизирај коментаре",
"reply_count": "{count} одговора",
"minimize_chapters_default": "Умањи поглавља подразумевано",
"show_watch_on_youtube": "Прикажите \"Гредај на YouTube-у\" дугме",
"no_valid_playlists": "Датотека не садржи важеће пописе снимака!",
"with_playlist": "Делите са пописом снимака",
"playlist_bookmarked": "Обиљежено",
"bookmark_playlist": "Биљежак",
"minimize_chapters_default": "Подразумевано минимизирај поглавља",
"show_watch_on_youtube": "Прикажи дугме „Гледај на YouTube-у“",
"no_valid_playlists": "Фајл не садржи важеће плејлисте!",
"with_playlist": "Дели са плејлистом",
"playlist_bookmarked": "Обележено",
"bookmark_playlist": "Обележивач",
"show_less": "Прикажи мање",
"skip_button_only": "Прикажи дугме за прескакање",
"skip_automatically": "Аутоматски",
"min_segment_length": "Најмања дужина сегмента (у секундама)",
"min_segment_length": "Минимална дужина сегмента (у секундама)",
"skip_segment": "Прескочи сегмент",
"dismiss": "Одбаци",
"autoplay_next_countdown": "Подразумевано одбројавање до следећег видеа (у секундама)"
"autoplay_next_countdown": "Подразумевано одбројавање до следећег видео снимка (у секундама)",
"okay": "У реду",
"edit_playlist": "Измени плејлисту",
"group_name": "Име групе",
"add_to_group": "Додај у групу",
"import_from_json_csv": "Увези из JSON-а/CSV-а",
"cancel": "Откажи",
"enable_dearrow": "Омогући DeArrow",
"playlist_description": "Опис плејлисте",
"chapters_layout_mobile": "Изглед поглавља на мобилном уређају",
"delete_automatically": "Избриши аутоматски након",
"download_frame": "Преузми кадар",
"create_group": "Направи групу",
"show_search_suggestions": "Прикажи предлоге за претрагу",
"auto_display_captions": "Аутоматски прикажи титлове",
"generate_qrcode": "Генериши QR кôд",
"playlist_name": "Назив плејлисте",
"instance_privacy_policy": "Политика приватности",
"instances_not_shown": "Јавне инстанце које нису приказане овде тренутно нису доступне.",
"concurrent_prefetch_limit": "Ограничење претходног преузимања истовремених стримова",
"invalid_url": "Неважећа URL адреса!",
"add": "Додај",
"customize": "Прилагоди",
"delete_group_confirm": "Избрисати ову групу?",
"creator_replied": "Креатор је одговорио",
"creator_liked": "Креатор је лајковао",
"invalid_input": "Неважећи унос",
"playback_speed": "Брзина репродукције"
},
"preferences": {
"instance_locations": "Локација инстанце",
"instance_name": "Име инстанце",
"ssl_score": "SSL скор/оцена",
"has_cdn": "Да ли поседује CDN?",
"instance_locations": "Локације инстанце",
"instance_name": "Назив инстанце",
"ssl_score": "SSL оцена",
"has_cdn": "Поседује ли CDN?",
"registered_users": "Регистровани корисници",
"version": "Верзија",
"up_to_date": "Ажурирано?"
"up_to_date": "Ажурирано?",
"uptime_30d": "Време рада (30д)",
"api_url": "URL API-ја"
},
"login": {
"password": "Лозинка",
"username": "Корисничко име"
"username": "Корисничко име",
"password_confirm": "Потврдите лозинку",
"passwords_incorrect": "Лозинке се не подударају!"
},
"search": {
"did_you_mean": "Да ли сте мислили: {0}?",
"did_you_mean": "Мислили сте: {0}?",
"all": "YouTube: Све",
"videos": "YouTube: Видеи",
"videos": "YouTube: Видео снимци",
"channels": "YouTube: Канали",
"playlists": "YouTube: Пописи снимака",
"playlists": "YouTube: Плејлисте",
"music_songs": "YT Music: Песме",
"music_videos": "YT Music: Видеи",
"music_videos": "YT Music: Видео снимци",
"music_albums": "YT Music: Албуми",
"music_playlists": "YT Music: Пописи снимака"
"music_playlists": "YT Music: Плејлисте",
"music_artists": "YT Music: Извођачи"
},
"titles": {
"history": "Повест гледања",
"feed": "Новости",
"history": "Историја",
"feed": "Фид",
"preferences": "Подешавања",
"register": "Регистрација",
"trending": "У тренду",
"login": "Пријава",
"subscriptions": "Праћења",
"playlists": описи Снимака",
"account": "Рачун",
"playlists": лејлисте",
"account": "Налог",
"instance": "Инстанца",
"player": окретник",
"livestreams": "Уживо преноси",
"player": лејер",
"livestreams": "Стримови уживо",
"channels": "Канали",
"bookmarks": "Биљешци"
"bookmarks": "Обележивачи",
"channel_groups": "Групе канала",
"dearrow": "DeArrow",
"albums": "Албуми",
"custom_instances": "Прилагођене инстанце"
},
"comment": {
"pinned_by": "Закачено од {author}",
"disabled": "Преносник је онемогућио коментаре.",
"pinned_by": "Закачио {author}",
"disabled": "Аутор је онемогућио коментаре.",
"user_disabled": "Коментари су онемогућени у подешавањима.",
"loading": "Учитавање коментара..."
},
"player": {
"watch_on": "Гледај на {0}"
"watch_on": "Погледај на {0}",
"failed": "Неуспешно, са кодом грешке {0}, погледајте евиденцију за више информација"
},
"subscriptions": {
"subscribed_channels_count": "Претплаћени сте на: {0}"
"subscribed_channels_count": "Пратите: {0}"
},
"info": {
"page_not_found": "Страница није пронађена",
"copied": "Копирано!",
"cannot_copy": "Није могуће копирати!",
"preferences_note": "Напомена: подешавања се чувају у локалној меморији вашег претраживача. Брисање података прегледача ће их ресетовати.",
"local_storage": "Ова радња захтева локално складиште, да ли су колачићи омогућени ?",
"register_no_email_note": "Коришћење е-поруке као корисничког имена се не препоручује. Желите ли ипак наставити?",
"next_video_countdown": "Репродукује се следећи видео за {0}с"
"preferences_note": "Напомена: подешавања се чувају у локалној меморији вашег прегледача. Брисање података вашег прегледача ће их ресетовати.",
"local_storage": "Ова радња захтева localStorage, да ли су колачићи омогућени?",
"register_no_email_note": "Не препоручује се коришћење имејла као корисничког имена. Ипак наставити?",
"next_video_countdown": "Пушта се следећи видео снимак за {0}с.",
"hours": "{amount} сат(и)",
"login_note": "Пријавите се са налогом направљеним на овој инстанци.",
"months": "{amount} месец(а/и)",
"weeks": "{amount} недеља(е)",
"register_note": "Региструјте налог за ову Piped инстанцу. Ово ће вам омогућити да синхронизујете своја праћења и плејлисте са својим налогом, тако да се чувају на серверу. Можете користити све функције без налога, али сви подаци ће бити чувани у локалном кешу вашег прегледача. Уверите се да НЕ користите имејл-адресу као своје корисничко име и изаберите сигурну лозинку коју не користите на другим местима.",
"days": "{amount} дан(а)"
}
}

View file

@ -15,10 +15,11 @@
"dearrow": "DeArrow",
"livestreams": "Livesändningar",
"channels": "Kanaler",
"channel_groups": "Kanal Grupper"
"channel_groups": "Kanal Grupper",
"albums": "Album"
},
"actions": {
"subscribe": "Prenumerera - {count}",
"subscribe": "Prenumerera",
"channel_name_asc": "Kanalnamn (A-Z)",
"channel_name_desc": "Kanalnamn (Z-A)",
"back": "Tillbaka",
@ -28,7 +29,7 @@
"export_to_json": "Exportera till JSON",
"show_description": "Visa beskrivning",
"loading": "Laddar...",
"unsubscribe": "Avsluta prenumeration - {count}",
"unsubscribe": "Avsluta prenumeration",
"sort_by": "Sortera efter:",
"most_recent": "Senaste",
"skip_intro": "Hoppa över paus/introanimering",
@ -143,10 +144,13 @@
"skip_automatically": "Automatiskt",
"download_frame": "Ladda ner bildruta",
"import_from_json_csv": "Importera från JSON/CSV",
"instance_privacy_policy": "Sekretesspolicy"
"instance_privacy_policy": "Sekretesspolicy",
"add_to_group": "Lägg till i grupp",
"instances_not_shown": "Publika instanser som inte visas här är inte tillgängliga för närvarande.",
"concurrent_prefetch_limit": "Gräns för förhämtning av samtidig ström"
},
"player": {
"watch_on": "Titta på {0}",
"watch_on": "Se på {0}",
"failed": "Misslyckades med felkod {0}, se loggar för mer information"
},
"preferences": {
@ -156,7 +160,8 @@
"has_cdn": "Har CDN?",
"registered_users": "Registrerade användare",
"version": "Version",
"up_to_date": "Är du uppdaterad?"
"up_to_date": "Är du uppdaterad?",
"uptime_30d": "Upptid (30d)"
},
"login": {
"username": "Användarnamn",
@ -215,6 +220,8 @@
"cannot_copy": "Kan inte kopiera!",
"page_not_found": "Sida hittas ej",
"copied": "Kopierad!",
"local_storage": "Det här kräver localStorage, är cookies aktiverat?"
"local_storage": "Det här kräver localStorage, är cookies aktiverat?",
"login_note": "Logga in med ett konto som skapats på denna instans.",
"register_note": "Registrera ett konto för den här Piped-instansen. Då kan du synkronisera dina prenumerationer och spellistor med ditt konto, så att de lagras på serversidan. Du kan använda alla funktioner utan konto, men alla data lagras i webbläsarens lokala cache. Se till att du INTE använder en e-postadress som användarnamn och välj ett säkert lösenord som du inte använder någon annanstans."
}
}

View file

@ -8,8 +8,8 @@
"history": "வரலாறு"
},
"actions": {
"unsubscribe": "குழுவில் - {count}",
"subscribe": "குழுசேர் - {count}",
"unsubscribe": "குழுவில்",
"subscribe": "குழுசேர்",
"search": "தேடுக",
"yes": "ஆம்",
"no": "இல்லை",

View file

@ -11,7 +11,7 @@
"watch_on": "ดูบน {0}"
},
"actions": {
"unsubscribe": "เลิกติดตาม - {count}",
"unsubscribe": "เลิกติดตาม",
"view_subscriptions": "ดูการสมัครสมาชิก",
"channel_name_asc": "ชื่อช่อง (A-Z)",
"channel_name_desc": "ชื่อช่อง (Z-A)",
@ -20,7 +20,7 @@
"skip_sponsors": "ข้ามผู้สนับสนุน",
"skip_intro": "ข้ามช่วงพัก/แนะนำแอนิเมชั่น",
"skip_outro": "ข้ามภาพตอนจบ/เครดิต",
"subscribe": "ติดตาม - {count}",
"subscribe": "ติดตาม",
"sort_by": "เรียงตาม:",
"most_recent": "ล่าสุด",
"enable_sponsorblock": "เปิดใช้งานการบล็อกสปอนเซอร์"

View file

@ -31,8 +31,8 @@
"most_recent": "En Yeni",
"sort_by": "Sıralama ölçütü:",
"view_subscriptions": "Abonelikleri Görüntüle",
"unsubscribe": "Abonelikten Çık - {count}",
"subscribe": "Abone Ol - {count}",
"unsubscribe": "Abonelikten Çık",
"subscribe": "Abone Ol",
"enabled_codecs": "Etkin Çözücüler (Birden Çok)",
"enable_lbry_proxy": "LBRY için Vekil Sunucuyu Etkinleştir",
"disable_lbry": "Akış için LBRY'yi Devre Dışı Bırak",
@ -125,7 +125,18 @@
"generate_qrcode": "QR Kodu Oluştur",
"import_from_json_csv": "JSON/CSV Dosyasından İçe Aktar",
"download_frame": "Kareyi indir",
"instance_privacy_policy": "Gizlilik Politikası"
"instance_privacy_policy": "Gizlilik Politikası",
"add_to_group": "Gruba ekle",
"instances_not_shown": "Burada gösterilmeyen herkese açık sunucular şu anda kullanılamıyor.",
"concurrent_prefetch_limit": "Eşzamanlı Akış Ön Getirme Sınırı",
"invalid_url": "Geçersiz URL!",
"customize": "Özelleştir",
"add": "Ekle",
"delete_group_confirm": "Bu grup silinsin mi?",
"creator_replied": "Oluşturan yanıtladı",
"creator_liked": "Oluşturan beğendi",
"playback_speed": "Oynatma hızı",
"invalid_input": "Geçersiz giriş"
},
"player": {
"watch_on": "{0} üzerinde görüntüle",
@ -147,7 +158,9 @@
"channels": "Kanallar",
"bookmarks": "Yer İmleri",
"channel_groups": "Kanal grupları",
"dearrow": "DeArrow"
"dearrow": "DeArrow",
"albums": "Albümler",
"custom_instances": "Özel sunucular"
},
"video": {
"sponsor_segments": "Sponsorlar Bölümleri",
@ -172,7 +185,9 @@
"instance_name": "Sunucu Adı",
"registered_users": "Kayıtlı Kullanıcılar",
"version": "Sürüm",
"up_to_date": "Güncel Mi?"
"up_to_date": "Güncel Mi?",
"uptime_30d": "Çalışma Süresi (30g)",
"api_url": "API URL'si"
},
"comment": {
"pinned_by": "Şunun Tarafından Sabitlendi {author}",
@ -215,6 +230,8 @@
"days": "{amount} gün",
"months": "{amount} ay",
"hours": "{amount} saat",
"weeks": "{amount} hafta"
"weeks": "{amount} hafta",
"login_note": "Bu sunucuda oluşturulan bir hesapla oturum açın.",
"register_note": "Bu Piped sunucusu için bir hesap açın. Bu, aboneliklerinizi ve oynatma listelerinizi hesabınızla eşzamanlamanızı sağlar, böylece sunucu tarafında kaydedilirler. Tüm özellikleri bir hesap olmadan da kullanabilirsiniz, ancak bu şekilde tüm veriler yalnızca tarayıcınızınn yerel önbelleğinde saklanacaktır. Lütfen kullanıcı adı olarak bir e-posta adresi KULLANMADIĞINIZDAN ve başka bir yerde kullanmadığınız güvenli bir parola seçtiğinizden emin olun."
}
}

View file

@ -10,11 +10,11 @@
"passwords_incorrect": "Паролі не збігаються!"
},
"actions": {
"unsubscribe": "Відписатися - {count}",
"unsubscribe": "Відписатися",
"back": "Назад",
"skip_intro": "Пропускати паузу/заставку",
"dark": "Темна",
"view_subscriptions": "Переглянути Підписки",
"view_subscriptions": "Оглянути Підписки",
"channel_name_asc": "Назвою каналу (А-Я)",
"uses_api_from": "Використовує API від ",
"enable_sponsorblock": "Увімкнути Sponsorblock",
@ -31,18 +31,18 @@
"show_more": "Показати більше",
"no": "Ні",
"export_to_json": "Експортувати в JSON",
"minimize_description": "Згорнути опис",
"minimize_description": "Приховати опис",
"show_recommendations": "Показати рекомендації",
"enable_lbry_proxy": "Увімкнути проксі для LBRY",
"search": "Пошук (Ctrl+K)",
"clear_history": "Очистити історію перегляду",
"load_more_replies": "Завантажити більше відповідей",
"subscribe": "Підписатися - {count}",
"subscribe": "Підписатися",
"sort_by": "Сортувати за:",
"most_recent": "Найновішими",
"channel_name_desc": "Назвою каналу (Я-А)",
"least_recent": "Найстарішими",
"minimize_recommendations": "Згорнути рекомендації",
"minimize_recommendations": "Приховати рекомендації",
"skip_sponsors": "Пропускати спонсорську рекламу",
"skip_interaction": "Пропускати нагадування про взаємодію (підписка)",
"skip_non_music": "Пропускати сегменти без музики в музикальних відео",
@ -80,7 +80,7 @@
"show_markers": "Показувати маркери на програвачі",
"minimize_recommendations_default": "Згортати рекомендації за замовчуванням",
"logout": "Вийти з цього пристрою",
"backup_preferences": "Налаштування резервного копіювання",
"backup_preferences": "Резервне копіювання налаштувань",
"download_as_txt": "Завантажити як .txt",
"show_chapters": "Розділи",
"invalidate_session": "Вийти з усіх пристроїв",
@ -97,7 +97,7 @@
"documentation": "Документація",
"instance_auth_selection": "Екземпляр для автентифікації",
"minimize_chapters_default": "Згортати розділи за замовчуванням",
"show_watch_on_youtube": "Показати кнопку Дивитися на YouTube",
"show_watch_on_youtube": "Показувати кнопку Дивитися на YouTube",
"restore_preferences": "Відновити налаштування",
"different_auth_instance": "Використовувати інший екземпляр для автентифікації",
"clone_playlist_success": "Успішно клоновано!",
@ -107,7 +107,7 @@
"time_code": "Відмітка часу (у секундах)",
"reply_count": "{count} відповідей",
"minimize_comments_default": "Згортати коментарі за замовчуванням",
"minimize_comments": "Згорнути коментарі",
"minimize_comments": "Приховати коментарі",
"delete_account": "Видалити обліковий запис",
"no_valid_playlists": "Файл не містить дійсних списків відтворення!",
"bookmark_playlist": "Закладка",
@ -135,7 +135,18 @@
"generate_qrcode": "Згенерувати QR-код",
"import_from_json_csv": "Імпортувати з JSON/CSV",
"download_frame": "Завантажити кадр",
"instance_privacy_policy": "Політика конфіденційності"
"instance_privacy_policy": "Політика конфіденційності",
"add_to_group": "Додати до групи",
"instances_not_shown": "Публічні екземпляри, які не показані тут, наразі недоступні.",
"concurrent_prefetch_limit": "Обмеження одночасної передвибірки потоків",
"customize": "Налаштувати",
"invalid_url": "Неправильна URL-адреса!",
"add": "Додати",
"delete_group_confirm": "Видалити цю групу?",
"creator_replied": "Відповідь творця",
"creator_liked": "Творець уподобав(-ла)",
"invalid_input": "Неналежний ввід",
"playback_speed": "Швидкість відтворення"
},
"titles": {
"register": "Реєстрація",
@ -144,7 +155,7 @@
"history": "Історія перегляду",
"subscriptions": "Канали, на які ви підписані",
"trending": "Тренди",
"login": "Логін",
"login": "Увійти",
"playlists": "Списки відтворення",
"instance": "Екземпляр",
"player": "Програвач",
@ -153,7 +164,9 @@
"channels": "Канали",
"bookmarks": "Закладки",
"channel_groups": "Групи каналів",
"dearrow": "DeArrow"
"dearrow": "DeArrow",
"albums": "Альбоми",
"custom_instances": "Власні екземпляри"
},
"comment": {
"pinned_by": "Прикріплено користувачем {author}",
@ -168,7 +181,9 @@
"has_cdn": "Використовує CDN?",
"version": "Версія",
"up_to_date": "Версія актуальна?",
"registered_users": "Зареєстровано користувачей"
"registered_users": "Зареєстровано користувачів",
"uptime_30d": "Час роботи (30d)",
"api_url": "API URL-адреса"
},
"video": {
"videos": "Відео",
@ -203,15 +218,17 @@
},
"info": {
"copied": "Скопійовано!",
"cannot_copy": "Не вийшло скопіювати!",
"page_not_found": "Сторінка не знайдена",
"preferences_note": "Примітка: налаштування зберігаються в локальній пам'яті вашого браузера. Видалення даних браузера призведе до їх скидання.",
"cannot_copy": "Не вдало сь скопіювати!",
"page_not_found": "Сторінку не знайдено",
"preferences_note": "Примітка: налаштування зберігаються в локальній пам'яті вашого браузера. Видалення даних браузера призведе до скидання налаштувань.",
"local_storage": "Ця дія потребує localStorage, чи ввімкнуті файли cookie?",
"register_no_email_note": "Використання електронної пошти як імені користувача не рекомендується. Все одно продовжити?",
"next_video_countdown": "Наступне відео через {0} секунд",
"weeks": "{amount} тиждень(-і)",
"hours": "{amount} годин(-и)",
"months": "{amount} місяць(-і)",
"days": "{amount} день(-і)"
"days": "{amount} день(-і)",
"login_note": "Увійдіть за допомогою облікового запису, створеного на цьому екземплярі.",
"register_note": "Зареєструйте обліковий запис для цього екземпляра Piped. Це дозволить вам синхронізувати підписки та списки відтворення з вашим обліковим записом, щоб вони зберігалися на сервері. Ви також можете використовувати всі доступні функції без облікового запису, але всі дані будуть зберігатися в локальному кеші вашого браузера. Будь ласка, переконайтеся, що ви НЕ використовуєте свою адресу електронної пошти як ім'я користувача й обрали надійний пароль, який ви не використовуєте в інших місцях."
}
}

View file

@ -1,8 +1,8 @@
{
"actions": {
"subscribe": "Đăng ký - {count}",
"subscribe": "Đăng ký",
"autoplay_video": "Video tự động phát",
"unsubscribe": "Hủy đăng ký - {count}",
"unsubscribe": "Hủy đăng ký",
"view_subscriptions": "Xem những kênh đã đăng ký",
"sort_by": "Sắp xếp theo:",
"most_recent": "Gần đây nhất",
@ -20,17 +20,17 @@
"skip_interaction": "Bỏ qua lời nhắc tương tác (Đăng ký)",
"skip_preview": "Bỏ qua xem trước/tóm tắt",
"skip_self_promo": "Bỏ qua thanh toán/quảng cáo cho bản thân",
"skip_non_music": "Bỏ qua âm nhạc: Phần không phải âm nhạc",
"skip_highlight": "Bỏ qua phần đánh dấu",
"skip_non_music": "Âm nhạc: Bỏ qua phần không phải âm nhạc",
"skip_highlight": "Bỏ qua phần highlight",
"skip_filler_tangent": "Bỏ qua những đoạn không liên quan",
"country_selection": "Lựa chọn quốc gia",
"country_selection": "Quốc gia",
"default_homepage": "Trang chủ mặc định",
"show_comments": "Hiển thị bình luận",
"store_watch_history": "Lịch sử xem trên cửa hàng",
"language_selection": "Lựa chọn ngôn ngữ",
"language_selection": "Ngôn ngữ",
"instances_list": "Danh sách instance",
"show_more": "Hiện thị nhiều hơn",
"import_from_json": "Nhập từ JSON/CSV",
"import_from_json": "Nhập từ JSON",
"loop_this_video": "Lặp lại video này",
"channel_name_desc": "Tên kênh (Z-A)",
"default_quality": "Chất lượng mặc định",
@ -53,7 +53,7 @@
"light": "Sáng",
"audio_only": "Chỉ có âm thanh",
"minimize_description_default": "Thu nhỏ mô tả theo mặc định",
"instance_selection": "Lựa chọn instance",
"instance_selection": "Instance",
"yes": "Có",
"enabled_codecs": "Các codec được bật (Nhiều)",
"export_to_json": "Xuất định dạng JSON",
@ -82,7 +82,34 @@
"show_chapters": "Chương",
"show_less": "Hiển thị ít hơn",
"cancel": "Hủy",
"okay": "OK"
"okay": "OK",
"skip_button_only": "Hiện thị nút bỏ qua",
"edit_playlist": "Chỉnh sửa danh sách phát",
"invalidate_session": "Đăng xuất trên tất cả mọi thiết bị",
"playlist_description": "Mô tả danh sách phát",
"dismiss": "Bỏ qua",
"instance_donations": "Quyên góp cho instance này",
"store_search_history": "Lưu trữ lịch sử tìm kiếm",
"back_to_home": "Quay về trang chủ",
"show_search_suggestions": "Hiển thị gợi ý tìm kiếm",
"documentation": "Tài liệu hướng dẫn",
"generate_qrcode": "Tạo mã QR",
"playlist_name": "Tên danh sách phát",
"instance_privacy_policy": "Chính sách quyền riêng tư",
"delete_automatically": "Tự động xóa sau",
"download_frame": "Tải xuống frame",
"clone_playlist_success": "Đã nhân đôi thành công!",
"show_markers": "Hiển thị đánh dấu trên trình phát video",
"minimize_chapters_default": "Thu nhỏ các chương theo mặc định",
"bookmark_playlist": "Dấu trang (Bookmark)",
"clone_playlist": "Nhân đôi danh sách phát",
"enable_dearrow": "Bật DeArrow",
"different_auth_instance": "Sử dụng instance khác để xác thực",
"show_watch_on_youtube": "Hiển thị nút \"Xem trên YouTube\"",
"instances_not_shown": "Các instance công cộng nào mà không được hiển thị ở đây thì là vì nó hiện không thể dùng được.",
"auto_display_captions": "Tự động hiển thị phụ đề",
"autoplay_next_countdown": "Đếm ngược mặc định đến video tiếp theo (tính bằng giây)",
"instance_auth_selection": "Instance xác thực"
},
"titles": {
"register": "Đăng ký",
@ -97,7 +124,9 @@
"channels": "Kênh",
"instance": "Instance",
"player": "Trình phát video",
"livestreams": "Phát sóng trực tiếp"
"livestreams": "Phát sóng trực tiếp",
"bookmarks": "Dấu trang",
"dearrow": "DeArrow"
},
"player": {
"watch_on": "Xem trên {0}"
@ -115,11 +144,14 @@
"registered_users": "Người dùng đã đăng ký",
"version": "Phiên bản",
"up_to_date": "Đã được cập nhật?",
"ssl_score": "Điểm SSL"
"ssl_score": "Điểm SSL",
"uptime_30d": "Thời gian hoạt động (30 ngày)"
},
"login": {
"password": "Mật khẩu",
"username": "Tài khoản"
"username": "Tài khoản",
"password_confirm": "Nhập lại mật khẩu",
"passwords_incorrect": "Mật khẩu nhập lại không giống mật khẩu đầu tiên!"
},
"video": {
"views": "{views} lượt xem",
@ -130,7 +162,10 @@
"chapters": "Chương",
"videos": "Video",
"shorts": "Shorts",
"all": "Tất cả"
"all": "Tất cả",
"license": "Giấy phép",
"category": "Thể loại",
"visibility": "Chế độ hiển thị"
},
"search": {
"did_you_mean": "Ý của bạn là: {0}?",
@ -141,13 +176,21 @@
"music_playlists": "YT Music: Danh sách phát",
"videos": "YouTube: Video",
"music_videos": "YT Music: Video",
"music_albums": "YT Music: Album"
"music_albums": "YT Music: Album",
"music_artists": "YT Music: Nhạc sỹ"
},
"info": {
"copied": "Đã sao chép!",
"cannot_copy": "Không thể sao chép!",
"page_not_found": "Không tìm thấy trang",
"next_video_countdown": "Tự động phát video tiếp theo trong {0} giây"
"next_video_countdown": "Tự động phát video tiếp theo trong {0} giây",
"hours": "{amount} tiếng",
"months": "{amount} tháng",
"weeks": "{amount} tuần",
"register_no_email_note": "Không nên dùng địa chỉ email làm tên tài khoản. Bạn có chắc bạn muốn tiếp tục không?",
"days": "{amount} ngày",
"local_storage": "Hành động này cần localStorage, cookie có được bật không?",
"login_note": "Đăng nhập với một tài khoản được tạo trên instance này."
},
"subscriptions": {
"subscribed_channels_count": "Đã đăng ký cho: {0}"

View file

@ -45,8 +45,8 @@
"most_recent": "最新的",
"sort_by": "排序:",
"view_subscriptions": "查看订阅列表",
"unsubscribe": "取消订阅 - {count}",
"subscribe": "订阅 - {count}",
"unsubscribe": "取消订阅",
"subscribe": "订阅",
"loading": "正在加载...",
"filter": "筛选",
"search": "搜索 (Ctrl+K)",
@ -125,7 +125,18 @@
"generate_qrcode": "生成二维码",
"import_from_json_csv": "从 JSON/CSV 文件导入",
"download_frame": "下载视频帧",
"instance_privacy_policy": "隐私政策"
"instance_privacy_policy": "隐私政策",
"add_to_group": "添加到组",
"instances_not_shown": "未显示在此处的公共实例当前不可用。",
"concurrent_prefetch_limit": "并行流预获取限制",
"customize": "自定义",
"invalid_url": "无效的 URL",
"add": "添加",
"delete_group_confirm": "删除该组吗?",
"creator_replied": "创作者回复了",
"creator_liked": "创作者点赞了",
"playback_speed": "播放速度",
"invalid_input": "无效输入"
},
"video": {
"sponsor_segments": "赞助商部分",
@ -134,7 +145,7 @@
"videos": "视频",
"live": "{0} 直播",
"chapters": "章节",
"ratings_disabled": "已禁用评价",
"ratings_disabled": "评分已禁用",
"shorts": "短视频",
"all": "全部",
"category": "类别",
@ -150,7 +161,9 @@
"instance_name": "实例名称",
"version": "版本",
"up_to_date": "最新?",
"registered_users": "已注册用户"
"registered_users": "已注册用户",
"uptime_30d": "在线时间30天",
"api_url": "Api URL"
},
"comment": {
"pinned_by": "固定自 {author}",
@ -178,7 +191,9 @@
"channels": "频道",
"bookmarks": "书签",
"channel_groups": "频道组",
"dearrow": "DeArrow"
"dearrow": "DeArrow",
"albums": "专辑",
"custom_instances": "自定义实例"
},
"login": {
"password": "密码",
@ -215,6 +230,8 @@
"days": "{amount} 天",
"weeks": "{amount} 周",
"months": "{amount} 个月",
"hours": "{amount} 小时"
"hours": "{amount} 小时",
"login_note": "使用在此实例上创建的账户登录。",
"register_note": "在这个 Piped 实例上注册一个账户。你可以通过账户同步订阅和播放列表,所有数据存储在实例的服务器上。没有账户你也可以使用所有功能,但数据均储存在你所用浏览器的本地缓存中。请确保你没有将电子邮箱地址用作账户的用户名,并选择一个你不在其他地方使用的安全密码。"
}
}

View file

@ -6,8 +6,8 @@
"country_selection": "國家",
"channel_name_desc": "頻道名 (Z-A)",
"channel_name_asc": "頻道名 (A-Z)",
"unsubscribe": "取消訂閱 - {count}",
"subscribe": "訂閱 - {count}",
"unsubscribe": "取消訂閱",
"subscribe": "訂閱",
"sort_by": "排序依據:",
"view_subscriptions": "檢視訂閱內容",
"language_selection": "語言",
@ -16,7 +16,7 @@
"show_description": "顯示說明",
"least_recent": "最早",
"skip_interaction": "跳過互動(訂閱)提醒",
"skip_self_promo": "跳過無酬自我行銷",
"skip_self_promo": "跳過無酬/自我行銷",
"audio_only": "僅聲音",
"default_quality": "預設品質",
"show_comments": "顯示留言",
@ -28,8 +28,8 @@
"minimize_recommendations": "最小化推薦",
"most_recent": "最新",
"back": "返回",
"skip_outro": "跳過片尾插圖工作人員名單",
"skip_preview": "跳過預覽回顧",
"skip_outro": "跳過片尾插圖/工作人員名單",
"skip_preview": "跳過預覽/回顧",
"autoplay_video": "自動播放影片",
"buffering_goal": "緩衝目標(秒)",
"skip_highlight": "跳過精采整理",
@ -42,7 +42,7 @@
"yes": "是",
"no": "否",
"export_to_json": "以 JSON 匯出",
"import_from_json": "從 JSON/CSV 匯入",
"import_from_json": "從 JSON 匯入",
"loop_this_video": "循環播放此影片",
"auto_play_next_video": "自動播放下一部影片",
"donations": "開發捐款",
@ -61,7 +61,7 @@
"delete_playlist_video_confirm": "要從播放清單中移除影片嗎?",
"delete_account": "刪除帳戶",
"show_chapters": "章節",
"download_as_txt": "以 .txt 下載",
"download_as_txt": "下載為 .txt",
"share": "分享",
"reset_preferences": "重設偏好設定",
"confirm_reset_preferences": "確定要重設偏好設定嗎?",
@ -82,12 +82,12 @@
"view_ssl_score": "查看 SSL 分數",
"logout": "從這個設置登出",
"minimize_comments_default": "預設為收起留言",
"instance_selection": "選擇站台",
"instance_selection": "站台",
"skip_automatically": "自動",
"skip_segment": "跳過分段",
"edit_playlist": "編輯播放清單",
"playlist_name": "播放清單名稱",
"instance_auth_selection": "選擇身分驗證站台",
"instance_auth_selection": "身分驗證站台",
"instance_donations": "站台捐款",
"invalidate_session": "從所有裝置登出",
"clone_playlist": "複製播放清單",
@ -120,7 +120,13 @@
"minimize_recommendations_default": "預設收起推薦影片",
"show_watch_on_youtube": "顯示「在Youtube 觀看」按鈕",
"show_less": "顯示更少",
"generate_qrcode": "產生 QR 碼"
"generate_qrcode": "產生 QR 碼",
"add_to_group": "加到群組",
"import_from_json_csv": "從 JSON / CSV 匯入",
"enable_dearrow": "啟用 DeArrow 插件",
"delete_automatically": "在多久後自動刪除",
"download_frame": "下載影片幀",
"instance_privacy_policy": "私隱政策"
},
"titles": {
"history": "歷史記錄",
@ -137,7 +143,8 @@
"bookmarks": "書籤",
"livestreams": "直播",
"channels": "頻道",
"channel_groups": "頻道群組"
"channel_groups": "頻道群組",
"dearrow": "DeArrow 插件"
},
"preferences": {
"registered_users": "已註冊的使用者",
@ -151,7 +158,8 @@
"login": {
"username": "使用者名",
"password": "密碼",
"password_confirm": "確認密碼"
"password_confirm": "確認密碼",
"passwords_incorrect": "密碼不正確!"
},
"video": {
"videos": "影片",
@ -165,7 +173,9 @@
"chapters_vertical": "垂直",
"views": "觀看次數:{views}",
"live": "{0} 直播",
"all": "全部"
"all": "全部",
"visibility": "是否顯示",
"license": "授權"
},
"search": {
"did_you_mean": "您是否想找 {0}",
@ -196,10 +206,13 @@
"days": "{amount} 天",
"weeks": "{amount} 個星期",
"months": "{amount} 個月",
"hours": "{amount} 小時"
"hours": "{amount} 小時",
"login_note": "使用在此站台中註冊的賬戶登錄。",
"register_note": "你可以在這個 Piped 站台註冊一個賬戶。由於資料會存放在伺服器端,這會允許你透過你的帳戶同步你的訂閱和播放清單。你亦可在不註冊的情況下使用所有功能,但所有資料將會存放在瀏覽器端的緩存中。請不要使用電郵地址再為你的用戶名稱,並使用一個未在其他地方使用過的安全密碼。"
},
"player": {
"watch_on": "在 {0} 觀看"
"watch_on": "在 {0} 觀看",
"failed": "播放失敗,錯誤代碼 {0},詳情請翻查紀錄"
},
"subscriptions": {
"subscribed_channels_count": "己訂閱: {0}"

View file

@ -1,58 +1,4 @@
import { createApp } from "vue";
import { library } from "@fortawesome/fontawesome-svg-core";
import {
faEye,
faThumbtack,
faCheck,
faHeart,
faHeadphones,
faRss,
faChevronLeft,
faLevelDownAlt,
faTv,
faLevelUpAlt,
faBroadcastTower,
faCirclePlus,
faCircleMinus,
faXmark,
faClone,
faShare,
faBook,
faServer,
faDonate,
faBookmark,
faEdit,
} from "@fortawesome/free-solid-svg-icons";
import { faGithub, faBitcoin, faYoutube, faOdysee } from "@fortawesome/free-brands-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
library.add(
faEye,
faGithub,
faBitcoin,
faThumbtack,
faCheck,
faHeart,
faHeadphones,
faYoutube,
faOdysee,
faRss,
faChevronLeft,
faLevelDownAlt,
faLevelUpAlt,
faTv,
faBroadcastTower,
faCirclePlus,
faCircleMinus,
faXmark,
faClone,
faShare,
faBook,
faServer,
faDonate,
faBookmark,
faEdit,
);
import router from "@/router/router.js";
import "uno.css";
@ -178,7 +124,7 @@ const mixin = {
} else return defaultVal;
},
apiUrl() {
return this.getPreferenceString("instance", "https://pipedapi.kavin.rocks");
return this.getPreferenceString("instance", import.meta.env.VITE_PIPED_API);
},
authApiUrl() {
if (this.getPreferenceBoolean("authInstance", false)) {
@ -243,6 +189,48 @@ const mixin = {
const localSubscriptions = this.getLocalSubscriptions() ?? [];
return localSubscriptions.join(",");
},
async fetchSubscriptions() {
if (this.authenticated) {
return await this.fetchJson(this.authApiUrl() + "/subscriptions", null, {
headers: {
Authorization: this.getAuthToken(),
},
});
} else {
const channels = this.getUnauthenticatedChannels();
const split = channels.split(",");
if (split.length > 100) {
return await this.fetchJson(this.authApiUrl() + "/subscriptions/unauthenticated", null, {
method: "POST",
body: JSON.stringify(split),
});
} else {
return await this.fetchJson(this.authApiUrl() + "/subscriptions/unauthenticated", {
channels: this.getUnauthenticatedChannels(),
});
}
}
},
async fetchFeed() {
if (this.authenticated) {
return await this.fetchJson(this.authApiUrl() + "/feed", {
authToken: this.getAuthToken(),
});
} else {
const channels = this.getUnauthenticatedChannels();
const split = channels.split(",");
if (split.length > 100) {
return await this.fetchJson(this.authApiUrl() + "/feed/unauthenticated", null, {
method: "POST",
body: JSON.stringify(split),
});
} else {
return await this.fetchJson(this.authApiUrl() + "/feed/unauthenticated", {
channels: channels,
});
}
}
},
/* generate a temporary file and ask the user to download it */
download(text, filename, mimeType) {
var file = new Blob([text], { type: mimeType });
@ -254,11 +242,26 @@ const mixin = {
elem.click();
elem.remove();
},
getChannelGroupsCursor() {
if (!window.db) return;
var tx = window.db.transaction("channel_groups", "readonly");
var store = tx.objectStore("channel_groups");
return store.index("groupName").openCursor();
async getChannelGroups() {
return new Promise(resolve => {
let channelGroups = [];
var tx = window.db.transaction("channel_groups", "readonly");
var store = tx.objectStore("channel_groups");
const cursor = store.index("groupName").openCursor();
cursor.onsuccess = e => {
const cursor = e.target.result;
if (cursor) {
const group = cursor.value;
channelGroups.push({
groupName: group.groupName,
channels: JSON.parse(group.channels),
});
cursor.continue();
} else {
resolve(channelGroups);
}
};
});
},
createOrUpdateChannelGroup(group) {
var tx = window.db.transaction("channel_groups", "readwrite");
@ -351,7 +354,7 @@ const mixin = {
});
},
async getPlaylist(playlistId) {
if (!this.authenticated) {
if (playlistId.startsWith("local")) {
const playlist = await this.getLocalPlaylist(playlistId);
const videoIds = JSON.parse(playlist.videoIds);
const videosFuture = videoIds.map(videoId => this.getLocalPlaylistVideo(videoId));
@ -371,7 +374,7 @@ const mixin = {
id: playlistId,
name: name,
description: "",
thumbnail: "https://pipedproxy.kavin.rocks/?host=i.ytimg.com",
thumbnail: import.meta.env.VITE_PIPED_PROXY + "/?host=i.ytimg.com",
videoIds: "[]", // empty list
});
return { playlistId: playlistId };
@ -495,7 +498,7 @@ const mixin = {
const videoIds = JSON.parse(playlist.videoIds);
videoIds.splice(index, 1);
playlist.videoIds = JSON.stringify(videoIds);
if (videoIds.length == 0) playlist.thumbnail = "https://pipedproxy.kavin.rocks/?host=i.ytimg.com";
if (videoIds.length == 0) playlist.thumbnail = import.meta.env.VITE_PIPED_PROXY + "/?host=i.ytimg.com";
this.createOrUpdateLocalPlaylist(playlist);
return { message: "ok" };
}
@ -542,6 +545,55 @@ const mixin = {
});
});
},
async fetchSubscriptionStatus(channelId) {
if (!this.authenticated) {
return this.isSubscribedLocally(channelId);
}
const response = await this.fetchJson(
this.authApiUrl() + "/subscribed",
{
channelId: channelId,
},
{
headers: {
Authorization: this.getAuthToken(),
},
},
);
return response?.subscribed;
},
async toggleSubscriptionState(channelId, subscribed) {
if (!this.authenticated) return this.handleLocalSubscriptions(channelId);
const resp = await this.fetchJson(this.authApiUrl() + (subscribed ? "/unsubscribe" : "/subscribe"), null, {
method: "POST",
body: JSON.stringify({
channelId: channelId,
}),
headers: {
Authorization: this.getAuthToken(),
"Content-Type": "application/json",
},
});
return !resp.error;
},
getCustomInstances() {
return JSON.parse(window.localStorage.getItem("customInstances")) ?? [];
},
addCustomInstance(instance) {
let customInstances = this.getCustomInstances();
customInstances.push(instance);
window.localStorage.setItem("customInstances", JSON.stringify(customInstances));
},
removeCustomInstance(instanceToDelete) {
let customInstances = this.getCustomInstances().filter(
instance => instance.api_url != instanceToDelete.api_url,
);
window.localStorage.setItem("customInstances", JSON.stringify(customInstances));
},
},
computed: {
authenticated(_this) {
@ -592,5 +644,4 @@ const app = createApp(App);
app.use(i18n);
app.use(router);
app.mixin(mixin);
app.component("FontAwesomeIcon", FontAwesomeIcon);
app.mount("#app");

View file

@ -33,7 +33,7 @@
/*Justify-Content: Space-Between*/ .pp-playlist-add-modal-top, .pp-watch-bellow-options, .pp-nav {justify-content: space-between}
/*Display: Flex*/ .pp-watch-buttons, .pp-watch-bellow-options .flex.items-center, .pp-channel-page-author, .grid .comment, .pp-chapters {display: flex}
/*Gap: 15rem*/ .pp-show-playlist, .pp-rec-vids, .pp-mobile-nav, .pp-delete-account .flex, .pp-playlist-add-modal-top, .pp-pref-cards, .pp-watch-bellow-options {gap: var(--efy_gap)}
/*Gap: 15rem*/ .pp-show-playlist, .pp-rec-vids, .pp-mobile-nav, .pp-delete-account .flex, .pp-playlist-add-modal-top, .pp-watch-bellow-options {gap: var(--efy_gap)}
/*Color: Text*/ .video-grid div a, .pp-show-recs div a, .video-grid div button:not(.modal button, .btn), .pp-show-recs div button:not(.modal button, .btn), .svg-inline--fa:not(.video-grid svg, [role=button] svg, button svg) {color: var(--efy_text)}
/*Border*/ .modal-container, .video-grid>div {border: 1.5px solid var(--efy_bg1);}
@ -94,9 +94,6 @@
/*Recommended Videos*/ .pp-rec-vids {display: grid; grid-template-columns: 1fr 300rem}
.order-first {-webkit-box-ordinal-group: -9998; -webkit-order: -9999; order: -9999}
/*Preferences*/ .pp-pref-cards {display: grid; grid-template-columns: repeat(auto-fit, minmax(300rem, 1fr))}
table {margin-top: 0}
/*Modal*/ .modal {backdrop-filter: blur(5px)}
.modal-container {background: var(--efy_text2)!important; padding: 15rem!important; box-shadow: 0 0 1px var(--efy_text_trans)}
.modal-container button + button {margin-left: 10rem}
@ -184,3 +181,8 @@ table {margin-top: 0}
@media (min-width: 768px) {
.md\:hidden {display: none}
}
/*Temporary*/
[for="efy_mode_system"], #efy_mode_system {
display: none!important;
}

View file

@ -1,6 +1,7 @@
import {$, $all, $$, $add, $event, $ready} from '../node_modules/efy/efy.js';
import {$, $all, $$, $add, $event, $ready, $css_prop, efy} from '../node_modules/efy/efy.js';
$ready('#efy_sidebar', ()=>{
$add('div', {id: 'piped_efy_module'}, [], $('#efy_sidebar'), 'afterbegin');
/*Custom Menu*/ $add('div', {id: 'custom_sidebar_menu'}, [], $('#efy_modules'));
@ -16,7 +17,7 @@ $ready('#efy_sidebar', ()=>{
], $('#efy_modules'));
$add('mark', {efy_lang: 'alpha'}, [], $('#piped_style > summary'), 'beforeend');
/*Tabs*/ for (let a = ['comments', 'captions'], b = ['Comments', 'Captions'],
/*Tabs*/ for (let a = ['comments', 'captions', 'cards'], b = ['Comments', 'Captions', 'Cards'],
c = $('[efy_tabs=piped_style]'), i = 0; i < a.length; i++) {
const active = (a[i] === 'comments') ? {efy_active: ''} : null;
$add('button', {efy_tab: a[i], ...active}, [b[i]], $$(c, '.efy_tabs'));
@ -33,11 +34,25 @@ $ready('#efy_sidebar', ()=>{
$add('input', {type: 'checkbox', name: 'piped_style_captions', id: `piped_style_${a[i]}`}, [], c);
$add('label', {for: `piped_style_${a[i]}`}, [b[i]], c);
}
/*Comments & Captions*/ for (let a = ['comments_full', 'comments_nobg', 'captions-trans', 'captions-solid'],
b = ['.pp-comments', '.pp-comments', '.shaka-text-container', '.shaka-text-container'],
c = ['pp-full-width', 'pp-no-bg', 'pp-trans', 'pp-solid'], i = 0; i < a.length; i++) {
/*Cards*/ for (let a = 'cards_horizontal cards_old'.split(' '), b = ['Horizontal', 'Vertical'],
c = $('[efy_tabs=piped_style] [efy_content="cards"]'), i = 0; i < a.length; i++) {
$add('input', {type: 'checkbox', name: 'piped_style_cards', id: `piped_style_${a[i]}`}, [], c);
$add('label', {for: `piped_style_${a[i]}`}, [b[i]], c);
}
/*Comments & Captions*/ for (let a = ['comments_full', 'comments_nobg', 'captions-trans', 'captions-solid', 'cards_horizontal', 'cards_old'],
b = ['.pp-comments', '.pp-comments', '.player-container', '.player-container', 'body', 'body'],
c = ['pp-full-width', 'pp-no-bg', 'pp-trans', 'pp-solid', 'cards_horizontal', 'cards_old'], i = 0; i < a.length; i++) {
$event($(`#piped_style_${a[i]}`), 'click', ()=>{
$all(b[i]).forEach( (e)=>{ e.classList.toggle(c[i]) })
})
}
// Get EFY Color Gradient in Piped
let efy_colors = efy.colors;
efy_colors.forEach((a,i)=>{
let b = a.split(' '); b.shift(); b[3] = '/ ' + b[3];
efy_colors[i] = `oklch(${b.join(' ')})`;
});
$css_prop('--efy_piped_color1', String(efy_colors));
}, 1);

View file

@ -31,6 +31,11 @@ const routes = [
name: "WatchVideo",
component: () => import("../components/WatchVideo.vue"),
},
{
path: "/watch_videos",
name: "WatchVideos",
component: () => import("../components/WatchVideo.vue"),
},
{
path: "/clip/:clipId",
name: "Clips",

View file

@ -1,42 +1,33 @@
// Based of https://github.com/GilgusMaximus/yt-dash-manifest-generator/blob/master/src/DashGenerator.js
import { Buffer } from "buffer";
window.Buffer = Buffer;
import { json2xml } from "xml-js";
import { XMLBuilder } from "fast-xml-parser";
export function generate_dash_file_from_formats(VideoFormats, VideoLength) {
const generatedJSON = generate_xmljs_json_from_data(VideoFormats, VideoLength);
return json2xml(generatedJSON);
const builder = new XMLBuilder({
ignoreAttributes: false,
allowBooleanAttributes: true,
suppressBooleanAttributes: false,
attributeNamePrefix: "_",
});
return builder.build(generatedJSON);
}
function generate_xmljs_json_from_data(VideoFormatArray, VideoLength) {
const convertJSON = {
declaration: {
attributes: {
version: "1.0",
encoding: "utf-8",
"?xml": {
_version: "1.0",
_encoding: "utf-8",
MPD: {
_xmlns: "urn:mpeg:dash:schema:mpd:2011",
_profiles: "urn:mpeg:dash:profile:full:2011",
_minBufferTime: "PT1.5S",
_type: "static",
_mediaPresentationDuration: `PT${VideoLength}S`,
Period: {
AdaptationSet: generate_adaptation_set(VideoFormatArray),
},
},
},
elements: [
{
type: "element",
name: "MPD",
attributes: {
xmlns: "urn:mpeg:dash:schema:mpd:2011",
profiles: "urn:mpeg:dash:profile:full:2011",
minBufferTime: "PT1.5S",
type: "static",
mediaPresentationDuration: `PT${VideoLength}S`,
},
elements: [
{
type: "element",
name: "Period",
elements: generate_adaptation_set(VideoFormatArray),
},
],
},
],
};
return convertJSON;
}
@ -76,34 +67,27 @@ function generate_adaptation_set(VideoFormatArray) {
mimeAudioObjs.forEach(mimeAudioObj => {
const adapSet = {
type: "element",
name: "AdaptationSet",
attributes: {
id: mimeAudioObj.audioTrackId,
lang: mimeAudioObj.audioTrackId?.substr(0, 2),
mimeType: mimeAudioObj.mimeType,
startWithSAP: "1",
subsegmentAlignment: "true",
},
elements: [],
_id: mimeAudioObj.audioTrackId,
_lang: mimeAudioObj.audioTrackId?.substr(0, 2),
_mimeType: mimeAudioObj.mimeType,
_startWithSAP: "1",
_subsegmentAlignment: "true",
Representation: [],
};
let isVideoFormat = false;
if (mimeAudioObj.mimeType.includes("video")) {
isVideoFormat = true;
}
if (isVideoFormat) {
adapSet.attributes.scanType = "progressive";
adapSet["_scanType"] = "progressive";
}
for (var i = 0; i < mimeAudioObj.videoFormats.length; i++) {
const videoFormat = mimeAudioObj.videoFormats[i];
if (isVideoFormat) {
adapSet.elements.push(generate_representation_video(videoFormat));
adapSet.Representation.push(generate_representation_video(videoFormat));
} else {
adapSet.elements.push(generate_representation_audio(videoFormat));
adapSet.Representation.push(generate_representation_audio(videoFormat));
}
}
@ -114,94 +98,40 @@ function generate_adaptation_set(VideoFormatArray) {
function generate_representation_audio(Format) {
const representation = {
type: "element",
name: "Representation",
attributes: {
id: Format.itag,
codecs: Format.codec,
bandwidth: Format.bitrate,
_id: Format.itag,
_codecs: Format.codec,
_bandwidth: Format.bitrate,
AudioChannelConfiguration: {
_schemeIdUri: "urn:mpeg:dash:23003:3:audio_channel_configuration:2011",
_value: "2",
},
elements: [
{
type: "element",
name: "AudioChannelConfiguration",
attributes: {
schemeIdUri: "urn:mpeg:dash:23003:3:audio_channel_configuration:2011",
value: "2",
},
BaseURL: Format.url,
SegmentBase: {
_indexRange: `${Format.indexStart}-${Format.indexEnd}`,
Initialization: {
_range: `${Format.initStart}-${Format.initEnd}`,
},
{
type: "element",
name: "BaseURL",
elements: [
{
type: "text",
text: Format.url,
},
],
},
{
type: "element",
name: "SegmentBase",
attributes: {
indexRange: `${Format.indexStart}-${Format.indexEnd}`,
},
elements: [
{
type: "element",
name: "Initialization",
attributes: {
range: `${Format.initStart}-${Format.initEnd}`,
},
},
],
},
],
},
};
return representation;
}
function generate_representation_video(Format) {
const representation = {
type: "element",
name: "Representation",
attributes: {
id: Format.itag,
codecs: Format.codec,
bandwidth: Format.bitrate,
width: Format.width,
height: Format.height,
maxPlayoutRate: "1",
frameRate: Format.fps,
_id: Format.itag,
_codecs: Format.codec,
_bandwidth: Format.bitrate,
_width: Format.width,
_height: Format.height,
_maxPlayoutRate: "1",
_frameRate: Format.fps,
BaseURL: Format.url,
SegmentBase: {
_indexRange: `${Format.indexStart}-${Format.indexEnd}`,
Initialization: {
_range: `${Format.initStart}-${Format.initEnd}`,
},
},
elements: [
{
type: "element",
name: "BaseURL",
elements: [
{
type: "text",
text: Format.url,
},
],
},
{
type: "element",
name: "SegmentBase",
attributes: {
indexRange: `${Format.indexStart}-${Format.indexEnd}`,
},
elements: [
{
type: "element",
name: "Initialization",
attributes: {
range: `${Format.initStart}-${Format.initEnd}`,
},
},
],
},
],
};
return representation;
}