workflow: added linter and linted src/ folder

This commit is contained in:
Roberto Tonino 2021-05-23 18:46:03 +02:00
parent 0f2a1103fd
commit 3a58636d36
61 changed files with 7343 additions and 2498 deletions

15
.eslintrc.yml Normal file
View File

@ -0,0 +1,15 @@
---
extends:
- "@nuxtjs"
- plugin:prettier/recommended
plugins:
- "@typescript-eslint"
parserOptions:
parser: "@typescript-eslint/parser"
rules:
"@typescript-eslint/no-unused-vars":
- error
- args: all
argsIgnorePattern: ^_
no-unused-vars: off
no-console: off

4802
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -11,7 +11,8 @@
"minify": "esbuild public/js/bundle.temp.js --outfile=public/js/bundle.js --minify",
"dev": "npm-run-all --parallel serve watch:js",
"dev:gui": "npm-run-all --parallel serve:gui watch:js",
"build": "npm-run-all --sequential clean build:js minify clean-temp"
"build": "npm-run-all --sequential clean build:js minify clean-temp",
"lint": "eslint src/**/*.{js,vue} --fix"
},
"dependencies": {
"@vue/composition-api": "1.0.0-beta.21",
@ -25,14 +26,21 @@
"vuex": "^3.6.0"
},
"devDependencies": {
"@nuxtjs/eslint-config": "6.0.0",
"@rollup/plugin-alias": "^3.1.1",
"@rollup/plugin-commonjs": "^16.0.0",
"@rollup/plugin-node-resolve": "^10.0.0",
"@rollup/plugin-replace": "^2.3.4",
"@typescript-eslint/eslint-plugin": "4.21.0",
"@typescript-eslint/parser": "4.21.0",
"esbuild": "^0.8.22",
"eslint": "7.23.0",
"eslint-config-prettier": "^8.1.0",
"eslint-plugin-prettier": "3.3.1",
"node-sass": "^5.0.0",
"npm-run-all": "^4.1.5",
"postcss": "^8.2.1",
"prettier": "2.2.1",
"rimraf": "^3.0.2",
"rollup": "^2.35.0",
"rollup-plugin-analyzer": "^3.3.0",
@ -41,6 +49,7 @@
"rollup-plugin-vue": "4.2.0",
"sass": "^1.30.0",
"tailwindcss": "^1.9.6",
"typescript": "4.2.4",
"vue-template-compiler": "^2.6.12"
}
}

File diff suppressed because one or more lines are too long

View File

@ -14,7 +14,7 @@
<BaseLoadingPlaceholder
text="Connecting to local server..."
:hidden="isSocketConnected"
additionalClasses="absolute top-0 left-0 w-screen h-screen bg-black bg-opacity-50 z-50"
additional-classes="absolute top-0 left-0 w-screen h-screen bg-black bg-opacity-50 z-50"
/>
<TheTrackPreview />
@ -52,11 +52,6 @@ import TheContent from '@components/TheContent.vue'
import TheDownloadBar from '@components/downloads/TheDownloadBar.vue'
export default {
data() {
return {
isSocketConnected: false
}
},
components: {
TheSidebar,
TheSearchBar,
@ -68,9 +63,14 @@ export default {
TheContent
// ConfirmModal
},
data() {
return {
isSocketConnected: false
}
},
mounted() {
socket.addEventListener('open', (event) => {
console.log("Connected to WebSocket")
socket.addEventListener('open', event => {
console.log('Connected to WebSocket')
this.isSocketConnected = true
})
}

View File

@ -81,11 +81,11 @@ document.addEventListener('paste', pasteEvent => {
if (router.currentRoute.name === 'Link Analyzer') {
socket.emit('analyzeLink', pastedText)
} else {
if (pastedText.indexOf('\n') != -1) pastedText = pastedText.replace(/\n/g, ';')
if (pastedText.includes('\n')) pastedText = pastedText.replace(/\n/g, ';')
sendAddToQueue(pastedText)
}
} else {
let searchbar = document.querySelector('#searchbar')
const searchbar = document.querySelector('#searchbar')
searchbar.select()
searchbar.setSelectionRange(0, 99999)
}
@ -140,7 +140,7 @@ function loggedIn(data) {
break
case -1:
toast(i18n.t('toasts.deezerNotAvailable'), 'close', true, 'login-toast')
return
// TODO
// $('#open_login_prompt').show()
// document.getElementById('logged_in_info').classList.add('hide')

View File

@ -1,9 +1,9 @@
<template>
<main
id="content"
@scroll="$route.name === 'Search' ? handleContentScroll($event) : null"
ref="content"
aria-label="main content"
@scroll="$route.name === 'Search' ? handleContentScroll($event) : null"
>
<div id="container">
<BackButton v-if="showBackButton" class="sticky -ml-20" style="top: 1rem" />
@ -11,16 +11,16 @@
<keep-alive>
<router-view
v-if="!$route.meta.notKeepAlive"
:class="{ '-mt-16': showBackButton }"
:key="$route.fullPath"
:class="{ '-mt-16': showBackButton }"
:perform-scrolled-search="performScrolledSearch"
></router-view>
</keep-alive>
<router-view
v-if="$route.meta.notKeepAlive"
:class="{ '-mt-16': showBackButton }"
:key="$route.fullPath"
:class="{ '-mt-16': showBackButton }"
:perform-scrolled-search="performScrolledSearch"
></router-view>
</div>
@ -83,7 +83,7 @@ export default {
}),
computed: {
showBackButton() {
return ['Tracklist', 'Artist', 'Album', 'Playlist', 'Spotify Playlist'].indexOf(this.$route.name) !== -1
return ['Tracklist', 'Artist', 'Album', 'Playlist', 'Spotify Playlist'].includes(this.$route.name)
}
},
mounted() {

View File

@ -6,6 +6,7 @@
<input
id="searchbar"
ref="searchbar"
class="w-full"
autocomplete="off"
type="search"
@ -13,7 +14,6 @@
value=""
:placeholder="$t('searchbar')"
autofocus
ref="searchbar"
@keyup="performSearch($event)"
/>
<!-- @keyup.enter.exact="onEnter"
@ -134,20 +134,20 @@ export default defineComponent({
},
methods: {
async performSearch(keyEvent) {
let isEnterPressed = keyEvent.keyCode === 13
const isEnterPressed = keyEvent.keyCode === 13
if (!isEnterPressed) return
let term = this.$refs.searchbar.value
let isEmptySearch = term === ''
const term = this.$refs.searchbar.value
const isEmptySearch = term === ''
if (isEmptySearch) return
let isSearchingURL = isValidURL(term)
let isCtrlPressed = keyEvent.ctrlKey
let isShowingAnalyzer = this.$route.name === 'Link Analyzer'
let isShowingSearch = this.$route.name === 'Search'
let isSameAsLastSearch = term === this.lastTextSearch
const isSearchingURL = isValidURL(term)
const isCtrlPressed = keyEvent.ctrlKey
const isShowingAnalyzer = this.$route.name === 'Link Analyzer'
const isShowingSearch = this.$route.name === 'Search'
const isSameAsLastSearch = term === this.lastTextSearch
if (isSearchingURL) {
if (isCtrlPressed) {

View File

@ -217,14 +217,14 @@
const possibleStates = ['converting', 'downloading', 'download finished', 'completed']
export default {
props: {
queueItem: Object
},
data() {
return {
isLoading: false
}
},
props: {
queueItem: Object
},
computed: {
hasFails() {
return this.queueItem.failed >= 1
@ -242,7 +242,7 @@ export default {
return this.queueItem.status === 'download finished' && this.hasFails
},
isDeterminateStatus() {
return possibleStates.indexOf(this.queueItem.status) !== -1
return possibleStates.includes(this.queueItem.status)
},
barClass() {
return {
@ -292,14 +292,12 @@ export default {
if (this.queueItem.status === 'download finished') {
if (!this.hasFails) {
text = 'done'
} else {
if (this.queueItem.failed >= this.queueItem.size) {
} else if (this.queueItem.failed >= this.queueItem.size) {
text = 'error'
} else {
text = 'warning'
}
}
}
return text
}

View File

@ -1,29 +1,29 @@
<template>
<section
id="download_tab_container"
ref="container"
class="block h-screen bg-panels-bg text-foreground"
:class="{ 'tab-hidden': !isExpanded, 'w-8': !isExpanded }"
@transitionend="$refs.container.style.transition = ''"
ref="container"
:data-label="$t('downloads')"
aria-label="downloads"
@transitionend="$refs.container.style.transition = ''"
>
<!-- Drag handler -->
<div
v-show="isExpanded"
class="absolute w-4 h-full bg-grayscale-200"
@mousedown.prevent="startDrag"
style="cursor: ew-resize"
@mousedown.prevent="startDrag"
></div>
<!-- Bar toggler -->
<i
id="toggle_download_tab"
ref="toggler"
class="m-1 text-2xl cursor-pointer material-icons"
:class="{ 'ml-1': !isExpanded, 'ml-5': isExpanded }"
@click.prevent="toggleDownloadTab"
ref="toggler"
:title="$t('globals.toggle_download_tab_hint')"
@click.prevent="toggleDownloadTab"
></i>
<!-- Queue buttons -->
@ -39,23 +39,23 @@
>
folder_open
</i>
<i class="m-1 text-2xl cursor-pointer material-icons" @click="cleanQueue" :title="$t('globals.clean_queue_hint')">
<i class="m-1 text-2xl cursor-pointer material-icons" :title="$t('globals.clean_queue_hint')" @click="cleanQueue">
clear_all
</i>
<i
class="m-1 text-2xl cursor-pointer material-icons"
@click="cancelQueue"
:title="$t('globals.cancel_queue_hint')"
@click="cancelQueue"
>
delete_sweep
</i>
</div>
<div v-show="isExpanded" id="download_list" class="w-full pr-2" :class="{ slim: isSlim }" ref="list">
<div v-show="isExpanded" id="download_list" ref="list" class="w-full pr-2" :class="{ slim: isSlim }">
<QueueItem
v-for="item in queueList"
:queue-item="item"
:key="item.uuid"
:queue-item="item"
@show-errors="showErrorsTab"
@remove-item="onRemoveItem"
/>
@ -179,7 +179,7 @@ export default {
.catch(console.error)
// Check if download tab has slim entries
if ('true' === localStorage.getItem('slimDownloads')) {
if (localStorage.getItem('slimDownloads') === 'true') {
this.$refs.list.classList.add('slim')
}
@ -219,9 +219,11 @@ export default {
} = data
console.log({ initQueueList })
const initQueueComplete = Object.values(initQueueList).filter(el => ['completed', 'withErrors', 'failed'].includes(el.status)).map(el => el.uuid)
const initQueueComplete = Object.values(initQueueList)
.filter(el => ['completed', 'withErrors', 'failed'].includes(el.status))
.map(el => el.uuid)
console.log({initQueueComplete})
console.log({ initQueueComplete })
if (initQueueComplete && initQueueComplete.length) {
initQueueComplete.forEach(item => {
@ -274,7 +276,7 @@ export default {
const itemIsAlreadyDownloaded = queueItem.downloaded + queueItem.failed == queueItem.size
if (itemIsAlreadyDownloaded) {
const itemIsNotInCompletedQueue = this.queueComplete.indexOf(queueItem.uuid) == -1
const itemIsNotInCompletedQueue = !this.queueComplete.includes(queueItem.uuid)
this.$set(this.queueList[queueItem.uuid], 'status', 'download finished')
@ -283,7 +285,7 @@ export default {
this.queueComplete.push(queueItem.uuid)
}
} else {
const itemIsNotInQueue = this.queue.indexOf(queueItem.uuid) == -1
const itemIsNotInQueue = !this.queue.includes(queueItem.uuid)
if (itemIsNotInQueue) {
this.queue.push(queueItem.uuid)
@ -304,14 +306,14 @@ export default {
// downloaded and failed default to false?
const { uuid, downloaded, failed, progress, conversion, error, data, errid } = update
if (uuid && this.queue.indexOf(uuid) > -1) {
if (uuid && this.queue.includes(uuid)) {
if (downloaded) {
this.queueList[uuid].downloaded++
}
if (failed) {
this.queueList[uuid].failed++
this.queueList[uuid].errors.push({ message: error, data: data, errid: errid })
this.queueList[uuid].errors.push({ message: error, data, errid })
}
if (progress) {
@ -324,7 +326,7 @@ export default {
}
},
removeFromQueue(uuid) {
let index = this.queue.indexOf(uuid)
const index = this.queue.indexOf(uuid)
if (index > -1) {
this.$delete(this.queue, index)
@ -340,7 +342,7 @@ export default {
} else {
this.queue = [currentItem]
let tempQueueItem = this.queueList[currentItem]
const tempQueueItem = this.queueList[currentItem]
this.queueList = {}
this.queueList[currentItem] = tempQueueItem
@ -397,14 +399,14 @@ export default {
this.$set(this.queueList[uuid], 'status', 'downloading')
},
finishDownload(uuid) {
let isInQueue = this.queue.indexOf(uuid) > -1
const isInQueue = this.queue.includes(uuid)
if (!isInQueue) return
this.$set(this.queueList[uuid], 'status', 'download finished')
toast(this.$t('toasts.finishDownload', { item: this.queueList[uuid].title }), 'done')
let index = this.queue.indexOf(uuid)
const index = this.queue.indexOf(uuid)
if (index > -1) {
this.queue.splice(index, 1)

View File

@ -1,8 +1,8 @@
<template functional>
<div
v-show="!props.hidden"
class="flex justify-center items-center flex-col flex-1 h-full"
:class="props.additionalClasses"
v-show="!props.hidden"
>
<span class="mb-5">{{ props.text || 'Loading...' }}</span>
@ -58,4 +58,3 @@
}
}
</style>

View File

@ -1,6 +1,6 @@
<template>
<div class="wrapper" ref="wrapper">
<div class="body animate__animated animate__bounce" ref="body">
<div ref="wrapper" class="wrapper">
<div ref="body" class="body animate__animated animate__bounce">
<h1 style="flex: 1">{{ titleText }}</h1>
<div class="confirm-area">

View File

@ -10,10 +10,10 @@
<button
role="button"
aria-label="download"
v-on="$listeners"
:data-link="link"
class="absolute p-0 text-center bg-black border-0 rounded-full opacity-0 download_overlay hover:bg-primary"
tabindex="0"
v-on="$listeners"
>
<i class="text-white cursor-pointer material-icons" :title="$t('globals.download_hint')">get_app</i>
</button>

View File

@ -1,9 +1,9 @@
<template>
<i
@mouseenter="previewMouseEnter"
@mouseleave="previewMouseLeave"
class="absolute top-0 right-0 flex items-center justify-center w-full h-full text-center text-white transition-opacity duration-200 ease-in-out bg-black bg-opacity-50 rounded opacity-0 material-icons preview_controls"
:title="$t('globals.play_hint')"
@mouseenter="previewMouseEnter"
@mouseleave="previewMouseLeave"
>
play_arrow
</i>

View File

@ -1,10 +1,10 @@
<template>
<div class="context-menu" v-show="menuOpen" ref="contextMenu" :style="{ top: yPos, left: xPos }">
<div v-show="menuOpen" ref="contextMenu" class="context-menu" :style="{ top: yPos, left: xPos }">
<button
class="btn menu-option"
v-for="option of sortedOptions"
:key="option.label"
v-show="option.show"
:key="option.label"
class="btn menu-option"
@click.prevent="option.action"
>
<span class="menu-option__text">{{ option.label }}</span>
@ -91,7 +91,7 @@ export default {
}
}
let nextValuePosition = Object.values(options).length + 1
const nextValuePosition = Object.values(options).length + 1
downloadQualities.forEach((quality, index) => {
options[quality.objName] = {
@ -125,9 +125,9 @@ export default {
methods: {
showSearchbarMenu(url) {
console.log(url)
let searchbar = document.getElementById("searchbar")
const searchbar = document.getElementById('searchbar')
searchbar.dataset.cmLink = url
let contextMenuEvent = {
const contextMenuEvent = {
pageX: 115,
pageY: 57,
target: searchbar,

View File

@ -1,5 +1,5 @@
<template>
<div id="modal_quality" class="smallmodal" v-show="open" @click="tryToDownloadTrack($event)" ref="modal">
<div v-show="open" id="modal_quality" ref="modal" class="smallmodal" @click="tryToDownloadTrack($event)">
<div class="smallmodal-content">
<button class="btn btn-primary quality-button" data-quality-value="9">
{{ $t('globals.download', { thing: 'FLAC' }) }}

View File

@ -1,5 +1,5 @@
<template>
<audio id="preview-track" @canplay="onCanPlay" @timeupdate="onTimeUpdate" ref="preview">
<audio id="preview-track" ref="preview" @canplay="onCanPlay" @timeupdate="onTimeUpdate">
<source id="preview-track_source" src="" type="audio/mpeg" />
</audio>
</template>
@ -86,7 +86,7 @@ export default {
const { currentTarget: obj } = e
var icon = obj.tagName == 'I' ? obj : obj.querySelector('i')
const icon = obj.tagName == 'I' ? obj : obj.querySelector('i')
if (obj.hasAttribute('playing')) {
if (this.$refs.preview.paused) {
@ -133,7 +133,7 @@ export default {
}
},
async stopStackedTabsPreview() {
let controls = Array.prototype.slice.call(document.querySelectorAll('.preview_playlist_controls[playing]'))
const controls = Array.prototype.slice.call(document.querySelectorAll('.preview_playlist_controls[playing]'))
if (controls.length === 0) return
@ -161,4 +161,3 @@ export default {
}
}
</script>

View File

@ -5,10 +5,10 @@
<div
class="grid w-16 h-16 ml-auto rounded-full cursor-pointer bg-primary text-grayscale-870 place-items-center"
@click.stop="sendAddToQueue(downloadLink)"
aria-label="download"
role="button"
:data-cm-link="downloadLink"
@click.stop="sendAddToQueue(downloadLink)"
>
<i class="text-4xl material-icons" :title="$t('globals.download_hint')">get_app</i>
</div>
@ -18,8 +18,8 @@
<BaseTab
v-for="(item, name) in artistReleases"
:key="name"
@click="currentTab = name"
:class="{ active: currentTab === name }"
@click="currentTab = name"
>
{{ $tc(`globals.listTabs.${name}`, 2) }}
</BaseTab>
@ -31,7 +31,6 @@
<th
v-for="data in head"
:key="data.title"
@click="data.sortKey ? sortBy(data.sortKey) : null"
:style="{ width: data.width ? data.width : 'auto' }"
class="uppercase-first-letter"
:class="{
@ -40,6 +39,7 @@
sortable: data.sortKey,
clickable: data.sortKey
}"
@click="data.sortKey ? sortBy(data.sortKey) : null"
>
<!-- Need to change this behaviour for translations -->
{{ data.title }}
@ -74,9 +74,9 @@
<td class="w-32 text-center xl:w-40">{{ release.releaseDate }}</td>
<td class="w-20 text-center xl:w-32">{{ release.releaseTracksNumber }}</td>
<td
@click.stop="sendAddToQueue(release.releaseLink)"
:data-cm-link="release.releaseLink"
class="w-8 cursor-pointer"
@click.stop="sendAddToQueue(release.releaseLink)"
>
<i class="material-icons hover:text-primary" :title="$t('globals.download_hint')">file_download</i>
</td>

View File

@ -1,6 +1,6 @@
<template>
<div>
<h1 class="mb-8 text-5xl">{{ $t('charts.title') }} {{ country ? (`- ${country}`) : '' }}</h1>
<h1 class="mb-8 text-5xl">{{ $t('charts.title') }} {{ country ? `- ${country}` : '' }}</h1>
<div v-if="country === ''">
<div class="release-grid">
@ -14,7 +14,7 @@
role="button"
@click="getTrackList"
>
<img :src="release.picture_medium" class="w-full rounded coverart" :alt="release.title"/>
<img :src="release.picture_medium" class="w-full rounded coverart" :alt="release.title" />
</div>
</div>
</div>
@ -26,9 +26,9 @@
</button>
<table class="table table--charts">
<tbody>
<tr v-for="track, pos in chart" class="track_row">
<tr v-for="(track, pos) in chart" class="track_row">
<td :class="{ first: pos === 0 }" class="p-3 text-center cursor-default">
{{ pos+1 }}
{{ pos + 1 }}
</td>
<td class="table__icon table__icon--big">
<span
@ -107,13 +107,22 @@ export default {
},
computed: {
worldwideRelease() {
let worldwideRelease = this.countries.filter(country => {
const worldwideRelease = this.countries.filter(country => {
return country.title === 'Worldwide'
})
return worldwideRelease[0]
}
},
watch: {
id(newId) {
const isActualChart = newId !== 0
if (isActualChart) {
getChartTracks(newId).then(response => this.setTracklist(response.data))
}
}
},
async created() {
// socket.on('setChartTracks', this.setTracklist)
// this.$on('hook:destroyed', () => {
@ -180,15 +189,6 @@ export default {
localStorage.setItem('chart', this.country)
}
}
},
watch: {
id(newId) {
const isActualChart = newId !== 0
if (isActualChart) {
getChartTracks(newId).then(response => this.setTracklist(response.data))
}
}
}
}
</script>

View File

@ -35,5 +35,4 @@ export default {
}
</script>
<style>
</style>
<style></style>

View File

@ -223,7 +223,7 @@ export default defineComponent({
},
computed: {
activeTabEmpty() {
let toCheck = this.getActiveRelease()
const toCheck = this.getActiveRelease()
return toCheck?.length === 0
}
@ -233,10 +233,10 @@ export default defineComponent({
convertDuration,
downloadAllOfType() {
try {
let toDownload = this.getActiveRelease()
const toDownload = this.getActiveRelease()
if (this.activeTab === 'track') {
let lovedTracks = this.getLovedTracksPlaylist()
const lovedTracks = this.getLovedTracksPlaylist()
sendAddToQueue(lovedTracks.link)
} else {
@ -274,13 +274,13 @@ export default defineComponent({
return toDownload
},
getTabLength(tab = this.activeTab) {
let total = this[`${tab}s`]?.length
const total = this[`${tab}s`]?.length
// TODO: Add Spotify playlists to downlaod queue as well
//if (tab === "playlist") total += this.spotifyPlaylists.length
// if (tab === "playlist") total += this.spotifyPlaylists.length
return total || 0
},
getLovedTracksPlaylist() {
let lovedTracks = this.playlists.filter(playlist => {
const lovedTracks = this.playlists.filter(playlist => {
return playlist.is_loved_track
})

View File

@ -2,7 +2,7 @@
<div id="home_tab">
<h1 class="mb-8 text-5xl">{{ $t('globals.welcome') }}</h1>
<section class="py-6 border-0 border-t border-solid border-grayscale-500" ref="notLogged" v-if="!isLoggedIn">
<section v-if="!isLoggedIn" ref="notLogged" class="py-6 border-0 border-t border-solid border-grayscale-500">
<p id="home_not_logged_text" class="mb-4">{{ $t('home.needTologin') }}</p>
<router-link tag="button" class="btn btn-primary" name="button" :to="{ name: 'Settings' }">
{{ $t('home.openSettings') }}
@ -13,13 +13,13 @@
<h2 class="mb-6 text-3xl">{{ $t('home.sections.popularPlaylists') }}</h2>
<div class="release-grid">
<router-link
tag="div"
v-for="release in playlists"
:key="release.id"
tag="div"
class="release clickable"
:to="{ name: 'Playlist', params: { id: release.id } }"
@keyup.enter.native="$router.push({ name: 'Playlist', params: { id: release.id } })"
tabindex="0"
@keyup.enter.native="$router.push({ name: 'Playlist', params: { id: release.id } })"
>
<CoverContainer is-rounded :cover="release.picture_medium" :link="release.link" @click.stop="addToQueue" />
<p class="primary-text">{{ release.title }}</p>
@ -39,14 +39,14 @@
<h2 class="mb-6 text-3xl">{{ $t('home.sections.popularAlbums') }}</h2>
<div class="release-grid">
<router-link
tag="div"
v-for="release in albums"
:key="release.id"
tag="div"
class="release clickable"
:to="{ name: 'Album', params: { id: release.id } }"
@keyup.enter.native="$router.push({ name: 'Album', params: { id: release.id } })"
:data-id="release.id"
tabindex="0"
@keyup.enter.native="$router.push({ name: 'Album', params: { id: release.id } })"
>
<CoverContainer is-rounded :cover="release.cover_medium" :link="release.link" @click.stop="addToQueue" />
<p class="primary-text">{{ release.title }}</p>
@ -100,5 +100,4 @@ export default {
}
</script>
<style>
</style>
<style></style>

View File

@ -2,9 +2,9 @@
<div>
<h1 class="mb-8 text-5xl">{{ $t('settings.login.arl.question') }}</h1>
<p class="mb-2 text-base">
Deezer keeps track of login session by using a cookie called ARL.<br>
deemix uses that cookie to get the metadata that it needs to download the tracks from Deezer.<br>
ARLs last for 3 months, after that Deezer asks you to log in again. The same method is used in deemix<br>
Deezer keeps track of login session by using a cookie called ARL.<br />
deemix uses that cookie to get the metadata that it needs to download the tracks from Deezer.<br />
ARLs last for 3 months, after that Deezer asks you to log in again. The same method is used in deemix<br />
Following one of the guides below you can get your own account ARL.
</p>
@ -26,7 +26,7 @@
<li>Go under the Application tab (if you don't see it click the double arrow)</li>
<li>Open the cookie dropdown</li>
<li>Select www.deezer.com</li>
<li>Find the `arl` cookie (It should be 192 chars long) </li>
<li>Find the `arl` cookie (It should be 192 chars long)</li>
<li>That's your ARL, now you can use it in the app</li>
</ul>

View File

@ -2,30 +2,39 @@
<div>
<h1 class="mb-8 text-5xl">{{ $t('settings.spotify.question') }}</h1>
<p class="mb-2 text-base">
"Spotify Features" is a set of features that lets you convert Spotify tracks and albums links into Deezer ones.
If you provide a Spotify Playlist link the app will autmatically convert all the links of the tracks inside it into deezer tracks.
Enabling this set of features will let you see your public Spotify playlists in the favorites tab as well.
"Spotify Features" is a set of features that lets you convert Spotify tracks and albums links into Deezer ones. If
you provide a Spotify Playlist link the app will autmatically convert all the links of the tracks inside it into
deezer tracks. Enabling this set of features will let you see your public Spotify playlists in the favorites tab
as well.
</p>
<p class="mb-2 text-base">For security reasons you will need to provide your own Client ID and Secret</p>
<h2 class="mt-6 text-3xl">How do I get my Client ID and Secret?</h2>
<p class="mb-2 text-base">Connect to <a href="https://developer.spotify.com/dashboard" target="_blank">Spotify for Developers's Dashboard</a> and login with your Spotify account.</p>
<p class="mb-2 text-base">
Click on "Create an App".<br>
<img src="https://i.imgur.com/YFz7rHj.png" alt="Create an App button on Spotify for Developers's Dashboard">
Connect to
<a href="https://developer.spotify.com/dashboard" target="_blank">Spotify for Developers's Dashboard</a> and login
with your Spotify account.
</p>
<p class="mb-2 text-base">
Fill out the "App name" and "App description" fields and check both checkboxes. Then click on the "Create" button.<br>
<img src="https://i.imgur.com/A9cvDkK.png" alt="Create an app form">
Click on "Create an App".<br />
<img src="https://i.imgur.com/YFz7rHj.png" alt="Create an App button on Spotify for Developers's Dashboard" />
</p>
<p class="mb-2 text-base">
Now you can see the Client ID. If you click on "Show Client Secret" the client secret will be revealed.<br>
<img src="https://i.imgur.com/foEfIhO.png" alt="Screen of client ID and Secret">
Fill out the "App name" and "App description" fields and check both checkboxes. Then click on the "Create"
button.<br />
<img src="https://i.imgur.com/A9cvDkK.png" alt="Create an app form" />
</p>
<p class="mb-2 text-base">
Now you can see the Client ID. If you click on "Show Client Secret" the client secret will be revealed.<br />
<img src="https://i.imgur.com/foEfIhO.png" alt="Screen of client ID and Secret" />
</p>
<p class="mb-2 text-base">Now you can copy-paste those results in the appropriate fields in the settings.</p>
<h2 class="mt-6 text-3xl">How do I get my Spotify Username?</h2>
<p class="mb-2 text-base">You can get your Spotify Username from the <a href="https://www.spotify.com/it/account/overview/" target="_blank">Overview page on Spotify's Website</a>.</p>
<p class="mb-2 text-base">
You can get your Spotify Username from the
<a href="https://www.spotify.com/it/account/overview/" target="_blank">Overview page on Spotify's Website</a>.
</p>
</div>
</template>
@ -33,5 +42,4 @@
export default {}
</script>
<style>
</style>
<style></style>

View File

@ -65,10 +65,10 @@
<div
role="button"
aria-label="download"
@contextmenu.prevent="openQualityModal"
@click.stop="addToQueue"
:data-link="link"
class="grid w-16 h-16 ml-auto rounded-full cursor-pointer bg-primary text-grayscale-870 place-items-center"
@contextmenu.prevent="openQualityModal"
@click.stop="addToQueue"
>
<i class="text-4xl material-icons" :title="$t('globals.download_hint')">get_app</i>
</div>
@ -152,6 +152,11 @@ export default {
countries: []
}
},
mounted() {
socket.on('analyze_track', this.showTrack)
socket.on('analyze_album', this.showAlbum)
socket.on('analyze_notSupported', this.notSupported)
},
methods: {
convertDuration,
reset() {
@ -174,15 +179,15 @@ export default {
id
} = data
this.title = title + (title_version && title.indexOf(title_version) == -1 ? ' ' + title_version : '')
this.title = title + (title_version && !title.includes(title_version) ? ' ' + title_version : '')
this.image = cover_xl
this.type = 'track'
this.link = link
this.id = id
available_countries.forEach(cc => {
let temp = []
let chars = [...cc].map(c => c.charCodeAt() + 127397)
const temp = []
const chars = [...cc].map(c => c.charCodeAt() + 127397)
temp.push(String.fromCodePoint(...chars))
temp.push(COUNTRIES[cc])
this.countries.push(temp)
@ -207,14 +212,8 @@ export default {
addToQueue(e) {
sendAddToQueue(e.currentTarget.dataset.link)
}
},
mounted() {
socket.on('analyze_track', this.showTrack)
socket.on('analyze_album', this.showAlbum)
socket.on('analyze_notSupported', this.notSupported)
}
}
</script>
<style>
</style>
<style></style>

View File

@ -12,8 +12,8 @@
<BaseTab
v-for="tab in tabs"
:key="tab.name"
@click="changeSearchTab(tab.searchType)"
:class="{ active: currentTab.name === tab.name }"
@click="changeSearchTab(tab.searchType)"
>
{{ tab.name }}
</BaseTab>
@ -22,7 +22,7 @@
<keep-alive>
<component
:is="currentTab.component"
:viewInfo="getViewInfo()"
:view-info="getViewInfo()"
want-headers
@add-to-queue="addToQueue"
@change-search-tab="changeSearchTab"
@ -245,6 +245,22 @@ export default defineComponent({
return tabsLoaded
}
},
watch: {
performScrolledSearch(needToSearch) {
if (!needToSearch) return
this.scrolledSearch(needToSearch)
},
currentTab(newTab, old) {
if (this.isTabLoaded(newTab)) return
this.performSearch({
term: this.results.query,
type: newTab.searchType,
start: this.results[`${newTab.searchType}Tab`].next
})
}
},
methods: {
numberWithDots,
convertDuration,
@ -289,29 +305,10 @@ export default defineComponent({
}
},
isTabLoaded(tab) {
return this.loadedTabs.indexOf(tab.searchType) !== -1 || tab.searchType === 'all'
}
},
watch: {
performScrolledSearch(needToSearch) {
if (!needToSearch) return
this.scrolledSearch(needToSearch)
},
currentTab(newTab, old) {
if (this.isTabLoaded(newTab)) return
this.performSearch({
term: this.results.query,
type: newTab.searchType,
start: this.results[`${newTab.searchType}Tab`].next
})
return this.loadedTabs.includes(tab.searchType) || tab.searchType === 'all'
}
}
})
</script>
<style>
</style>
<style></style>

View File

@ -61,16 +61,18 @@
</div>
<div class="settings-group">
<h3 class="settings-group__header"><i class="material-icons">person</i>{{ $t('settings.loginWithCredentials.title') }}</h3>
<h3 class="settings-group__header">
<i class="material-icons">person</i>{{ $t('settings.loginWithCredentials.title') }}
</h3>
<form class="my-5 space-y-5" @submit.prevent="loginWithCredentials" ref="loginWithCredentialsForm">
<form ref="loginWithCredentialsForm" class="my-5 space-y-5" @submit.prevent="loginWithCredentials">
<label>
<span>Username</span>
<input type="text" name="username">
<input type="text" name="username" />
</label>
<label>
<span>Password</span>
<input type="password" name="password">
<input type="password" name="password" />
</label>
<button class="btn btn-primary" type="submit">{{ $t('settings.loginWithCredentials.login') }}</button>
@ -876,14 +878,14 @@ export default {
this.initSettings(settingsData, spotifyCredentials)
// TODO Move in store
let storedAccountNum = localStorage.getItem('accountNum')
const storedAccountNum = localStorage.getItem('accountNum')
if (storedAccountNum) {
this.accountNum = storedAccountNum
}
// TODO Move in store
let spotifyUser = localStorage.getItem('spotifyUser')
const spotifyUser = localStorage.getItem('spotifyUser')
if (spotifyUser) {
this.lastUser = spotifyUser
@ -924,7 +926,7 @@ export default {
this.spotifyUser = (' ' + this.lastUser).slice(1)
},
copyARLtoClipboard() {
let copyText = this.$refs.loginInput
const copyText = this.$refs.loginInput
copyText.setAttribute('type', 'text')
copyText.select()
@ -978,7 +980,7 @@ export default {
// const res = await fetchData('login', { arl, force: true, child: this.accountNum })
},
async login() {
let newArl = this.$refs.loginInput.value.trim()
const newArl = this.$refs.loginInput.value.trim()
if (newArl && newArl !== this.arl) {
const res = await fetchData('login-arl', { arl: newArl, force: true, child: this.accountNum }, 'POST')
@ -1020,7 +1022,7 @@ export default {
toast(this.$t('settings.toasts.init'), 'settings')
},
updateSettings(data) {
const {settings: newSettings, spotifySettings: newCredentials} = data
const { settings: newSettings, spotifySettings: newCredentials } = data
this.loadSettings(newSettings)
this.loadCredentials(newCredentials)

View File

@ -41,7 +41,6 @@
<td class="table__cell--x-small table__cell--center">
<div class="table__cell-content table__cell-content--vertical-center">
<i
v-on="{ click: track.preview ? playPausePreview : false }"
:class="{
preview_playlist_controls: track.preview,
'cursor-pointer': track.preview,
@ -50,6 +49,7 @@
:data-preview="track.preview"
:title="$t('globals.play_hint')"
class="material-icons"
v-on="{ click: track.preview ? playPausePreview : false }"
>
play_arrow
</i>

View File

@ -7,8 +7,8 @@
<h1>{{ $t('search.noResultsAlbum') }}</h1>
</div>
<div class="release-grid" v-else>
<div class="w-40 release" v-for="release in viewInfo.data.slice(0, itemsToShow)" :key="release.albumID">
<div v-else class="release-grid">
<div v-for="release in viewInfo.data.slice(0, itemsToShow)" :key="release.albumID" class="w-40 release">
<router-link tag="div" class="cursor-pointer" :to="{ name: 'Album', params: { id: release.albumID } }">
<CoverContainer
is-rounded
@ -53,9 +53,9 @@ export default {
},
props: {
viewInfo: {
validator: function (value) {
let isNull = Object.is(value, null)
let isObject = Object.prototype.toString.call(value) === '[object Object]'
validator(value) {
const isNull = Object.is(value, null)
const isObject = Object.prototype.toString.call(value) === '[object Object]'
return isNull || isObject
},

View File

@ -12,13 +12,13 @@
>
<template v-if="checkSectionResults(section)">
<h2
@click="$emit('change-search-tab', section)"
class="mb-6 capitalize"
:class="{
'text-4xl text-center': section === 'TOP_RESULT',
'inline-block cursor-pointer text-3xl hover:text-primary transition-colors duration-200 ease-in-out':
section !== 'TOP_RESULT'
}"
@click="$emit('change-search-tab', section)"
>
{{ $tc(`globals.listTabs.${section.toLowerCase()}`, 2) }}
</h2>
@ -31,29 +31,29 @@
<ResultsTracks
v-else-if="section === 'TRACK'"
:viewInfo="standardizeData(viewInfo.TRACK, formatSingleTrack)"
:itemsToShow="6"
:view-info="standardizeData(viewInfo.TRACK, formatSingleTrack)"
:items-to-show="6"
@add-to-queue="$emit('add-to-queue', $event)"
/>
<ResultsAlbums
v-else-if="section == 'ALBUM'"
:viewInfo="standardizeData(viewInfo.ALBUM, formatAlbums)"
:itemsToShow="6"
:view-info="standardizeData(viewInfo.ALBUM, formatAlbums)"
:items-to-show="6"
@add-to-queue="$emit('add-to-queue', $event)"
/>
<ResultsPlaylists
v-else-if="section == 'PLAYLIST'"
:viewInfo="standardizeData(viewInfo.PLAYLIST, formatPlaylist)"
:itemsToShow="6"
:view-info="standardizeData(viewInfo.PLAYLIST, formatPlaylist)"
:items-to-show="6"
@add-to-queue="$emit('add-to-queue', $event)"
/>
<ResultsArtists
v-else-if="section === 'ARTIST'"
:viewInfo="standardizeData(viewInfo.ARTIST, formatArtist)"
:itemsToShow="6"
:view-info="standardizeData(viewInfo.ARTIST, formatArtist)"
:items-to-show="6"
@add-to-queue="$emit('add-to-queue', $event)"
/>
</template>
@ -90,13 +90,13 @@ export default {
},
computed: {
thereAreResults() {
let areInfosLoaded = !!this.viewInfo
const areInfosLoaded = !!this.viewInfo
if (!areInfosLoaded) {
return false
}
let noResultsPresent = this.viewInfo.ORDER.every(section =>
const noResultsPresent = this.viewInfo.ORDER.every(section =>
section === 'TOP_RESULT' ? this.viewInfo[section].length === 0 : this.viewInfo[section].data.length === 0
)

View File

@ -8,7 +8,7 @@
</div>
<div v-else class="release-grid">
<div class="w-40 release" v-for="release in viewInfo.data.slice(0, itemsToShow)" :key="release.artistID">
<div v-for="release in viewInfo.data.slice(0, itemsToShow)" :key="release.artistID" class="w-40 release">
<router-link tag="div" class="cursor-pointer" :to="{ name: 'Artist', params: { id: release.artistID } }">
<CoverContainer
is-circle
@ -41,9 +41,9 @@ export default {
},
props: {
viewInfo: {
validator: function (value) {
let isNull = Object.is(value, null)
let isObject = Object.prototype.toString.call(value) === '[object Object]'
validator(value) {
const isNull = Object.is(value, null)
const isObject = Object.prototype.toString.call(value) === '[object Object]'
return isNull || isObject
},

View File

@ -6,8 +6,8 @@
<div v-if="viewInfo.data.length === 0">
<h1>{{ $t('search.noResultsPlaylist') }}</h1>
</div>
<div class="release-grid" v-else>
<div class="w-40 release" v-for="playlist in viewInfo.data.slice(0, itemsToShow)" :key="playlist.playlistID">
<div v-else class="release-grid">
<div v-for="playlist in viewInfo.data.slice(0, itemsToShow)" :key="playlist.playlistID" class="w-40 release">
<router-link tag="div" class="cursor-pointer" :to="{ name: 'Playlist', params: { id: playlist.playlistID } }">
<CoverContainer
is-rounded
@ -46,9 +46,9 @@ export default {
},
props: {
viewInfo: {
validator: function (value) {
let isNull = Object.is(value, null)
let isObject = Object.prototype.toString.call(value) === '[object Object]'
validator(value) {
const isNull = Object.is(value, null)
const isObject = Object.prototype.toString.call(value) === '[object Object]'
return isNull || isObject
},

View File

@ -24,9 +24,9 @@
<tr v-for="track in viewInfo.data.slice(0, itemsToShow)" :key="track.trackLink">
<td class="table__icon table__icon--big">
<span
@click="playPausePreview($event)"
class="relative inline-block rounded cursor-pointer"
:data-preview="track.trackPreview"
@click="playPausePreview($event)"
>
<PreviewControls v-if="track.trackPreview" />
@ -67,9 +67,9 @@
<td
class="cursor-pointer table__cell--center group"
@click.stop="$emit('add-to-queue', $event)"
:data-link="track.trackLink"
aria-label="download"
@click.stop="$emit('add-to-queue', $event)"
>
<i
class="transition-colors duration-150 ease-in-out material-icons group-hover:text-primary"
@ -101,9 +101,9 @@ export default {
},
props: {
viewInfo: {
validator: function (value) {
let isNull = Object.is(value, null)
let isObject = Object.prototype.toString.call(value) === '[object Object]'
validator(value) {
const isNull = Object.is(value, null)
const isObject = Object.prototype.toString.call(value) === '[object Object]'
return isNull || isObject
},

View File

@ -28,7 +28,6 @@
</div>
</template>
<script>
import { upperCaseFirstLowerCaseRest } from '@/utils/texts'
import CoverContainer from '@components/globals/CoverContainer.vue'
@ -37,9 +36,6 @@ export default {
components: {
CoverContainer
},
methods: {
upperCaseFirstLowerCaseRest
},
computed: {
fansNumber() {
let number
@ -56,6 +52,9 @@ export default {
' - ' +
this.$tc('globals.listTabs.trackN', this.$attrs.info.nb_song)
}
},
methods: {
upperCaseFirstLowerCaseRest
}
}
</script>

View File

@ -1,5 +1,5 @@
<template>
<BaseAccordion style="--arrow-v-align: baseline; margin-bottom: 3rem;">
<BaseAccordion style="--arrow-v-align: baseline; margin-bottom: 3rem">
<template #title>
<slot name="title"></slot>
</template>

View File

@ -10,7 +10,7 @@ export function formatArtistData(artistData) {
}
function formatArtistReleases(artistReleases) {
let formattedReleases = {}
const formattedReleases = {}
for (const releaseType in artistReleases) {
if (artistReleases.hasOwnProperty(releaseType)) {

View File

@ -54,7 +54,7 @@ export function formatAlbums(album) {
'EXPLICIT_ALBUM_CONTENT.EXPLICIT_LYRICS_STATUS'
)
if ('number' === typeof isAlbumExplicit) {
if (typeof isAlbumExplicit === 'number') {
isAlbumExplicit = isAlbumExplicit === 1
}
@ -95,9 +95,7 @@ export function formatPlaylist(playlist) {
playlistTitle: getPropertyWithFallback(playlist, 'title', 'TITLE'),
playlistPictureMedium:
getPropertyWithFallback(playlist, 'picture_medium') ||
`https://e-cdns-images.dzcdn.net/images/${playlist.PICTURE_TYPE}/${
playlist.PLAYLIST_PICTURE
}/156x156-000000-80-0-0.jpg`,
`https://e-cdns-images.dzcdn.net/images/${playlist.PICTURE_TYPE}/${playlist.PLAYLIST_PICTURE}/156x156-000000-80-0-0.jpg`,
playlistLink: getPropertyWithFallback(playlist, 'link') || `https://deezer.com/playlist/${playlist.PLAYLIST_ID}`,
playlistTracksNumber: getPropertyWithFallback(playlist, 'nb_tracks', 'NB_SONG'),
@ -107,7 +105,7 @@ export function formatPlaylist(playlist) {
}
export function formatTitle(track) {
const hasTitleVersion = track.trackTitleVersion && track.trackTitle.indexOf(track.trackTitleVersion) === -1
const hasTitleVersion = track.trackTitleVersion && !track.trackTitle.includes(track.trackTitleVersion)
return `${track.trackTitle}${hasTitleVersion ? ` ${track.trackTitleVersion}` : ''}`
}

View File

@ -4,12 +4,12 @@ let settingsData = {}
let defaultSettingsData = {}
let spotifyCredentials = {}
let cached = false
const cached = false
export async function getSettingsData() {
if (!cached) {
let data = await fetchData('getSettings')
let { settings, defaultSettings, spotifySettings } = data
const data = await fetchData('getSettings')
const { settings, defaultSettings, spotifySettings } = data
// cached = true
settingsData = settings
defaultSettingsData = defaultSettings
@ -36,12 +36,12 @@ export function getInitialPreviewVolume() {
* @returns {boolean}
*/
export function checkInitialSlimDownloads() {
return 'true' === localStorage.getItem('slimDownloads')
return localStorage.getItem('slimDownloads') === 'true'
}
/**
* @returns {boolean}
*/
export function checkInitialSlimSidebar() {
return 'true' === localStorage.getItem('slimSidebar')
return localStorage.getItem('slimSidebar') === 'true'
}

View File

@ -6,7 +6,7 @@ export function standardizeData(rawObj, formatFunc) {
const formattedData = []
for (const dataElement of rawData) {
let formatted = formatFunc(dataElement)
const formatted = formatFunc(dataElement)
formattedData.push(formatted)
}

View File

@ -39,11 +39,12 @@ const ar = {
license: 'الرخصة'
},
subtitles: {
bugReports: "هل هناك شيء لا يعمل في ديمكس؟ أخبرنا",
bugReports: 'هل هناك شيء لا يعمل في ديمكس؟ أخبرنا',
contributing: 'تريد المساهمة في هذا المشروع؟ يمكنك القيام بذلك بعدة طرق',
donations: 'تريد المساهمة مادياً؟ يمكنك التبرع'
},
usesLibrary: 'هذا البرنامج يستخدم مكتبة <strong>ديمكس</strong> والتي يمكنك استخدامها لإنشاء واجهة مستخدم خاصة بك لديمكس.',
usesLibrary:
'هذا البرنامج يستخدم مكتبة <strong>ديمكس</strong> والتي يمكنك استخدامها لإنشاء واجهة مستخدم خاصة بك لديمكس.',
thanks: `شكرا لـ <strong>rtonno</strong>, و <strong>uhwot</strong> و <strong>lollilol</strong> لمساعدتي في هذا المشروع و لـ <strong>BasCurtiz</strong> لصنع الايقونة.`,
officialWebsite: 'الموقع الرسمي',
officialRepo: 'مستودع المكتبة الرسمي',
@ -58,7 +59,7 @@ const ar = {
otherLanguages: `إذا كنت تجيد لغة برمجة أخرى ، يمكنك محاولة تحويل ديمكس إلى لغات برمجة أخرى!`,
understandingCode: `أنت بحاجة إلى مساعدة في فهم الكود؟ فقط اتصل بـ RemixDev على تيليكرام او ريديت.`,
itsFree: `يجب ان تتذكر ان <strong>هذا هو مشروع مجاني</strong> <strong>و عليك دعم الفنانين المفضلين لك قبل ان تدعم مطورين البرنامج</strong>.`,
notObligated: `لا تشعر بالالتزام بالتبرع ، لكني أقدر ذلك على أي حال!`,
notObligated: `لا تشعر بالالتزام بالتبرع ، لكني أقدر ذلك على أي حال!`
},
charts: {
title: 'قائمة الجداول',
@ -71,7 +72,7 @@ const ar = {
invalidURL: 'الرابط غير صحيح',
unsupportedURL: 'الرابط غير متاح حتى الانً',
ISRCnotOnDeezer: 'رمز المقطع غير متوفر في ديزر',
notYourPrivatePlaylist: "لا يمكنك تحميل قوائم التشغيل الخاصة و المخفية.",
notYourPrivatePlaylist: 'لا يمكنك تحميل قوائم التشغيل الخاصة و المخفية.',
spotifyDisabled: 'لم يتم اعداد ميزات سبوتفاي بالطرقة الصحيحة .',
trackNotOnDeezer: 'المقطع لا يوجد في ديزر!',
albumNotOnDeezer: 'الالبوم لا يوجد في ديزر!',
@ -81,8 +82,8 @@ const ar = {
wrongBitrate: 'لم يتم العثور على المقطع في الدقة المطلوبة.',
wrongBitrateNoAlternative: 'لم يتم العثور على المقطع في الدقة المطلوبة و لا توجد دقة بديلة!',
no360RA: 'المقطع غير متوفر في Reality Audio 360.',
notAvailable: "المقطع غير متوفر في سيرفرات ديزر!",
notAvailableNoAlternative: "المقطع غير متوفر في سيرفرات ديزر و لا يوجد بديل حتى الان!"
notAvailable: 'المقطع غير متوفر في سيرفرات ديزر!',
notAvailableNoAlternative: 'المقطع غير متوفر في سيرفرات ديزر و لا يوجد بديل حتى الان!'
}
},
favorites: {
@ -102,8 +103,7 @@ const ar = {
},
linkAnalyzer: {
info: 'يمكنك استخدام هذا القسم للعثور على مزيد من المعلومات حول الرابط الذي تحاول تنزيله.',
useful:
" كمثال هذا مفيد إذا كنت تحاول تنزيل بعض المقاطع الغير المتاحة في بلدك وتريد معرفة مكان توفرها .",
useful: ' كمثال هذا مفيد إذا كنت تحاول تنزيل بعض المقاطع الغير المتاحة في بلدك وتريد معرفة مكان توفرها .',
linkNotSupported: 'هذا الرابط غير معتمد حتى الآن',
linkNotSupportedYet: 'يبدو أن هذا الرابط غير معتمد حتى الآن ، حاول تحليل رابط آخر.',
table: {
@ -123,8 +123,7 @@ const ar = {
},
search: {
startSearching: 'ابدأ البحث!',
description:
'يمكنك البحث عن مقطع ، ألبوم كامل ، فنان ، قائمة تشغيل .... كل شيء! يمكنك أيضًا لصق رابط ديزر',
description: 'يمكنك البحث عن مقطع ، ألبوم كامل ، فنان ، قائمة تشغيل .... كل شيء! يمكنك أيضًا لصق رابط ديزر',
fans: '{n} متابعون',
noResults: 'لا يوجد نتائج',
noResultsTrack: 'لم يتم العثور على مقاطع',
@ -143,7 +142,7 @@ const ar = {
loggingIn: 'جار تسجيل الدخول...',
loggedIn: 'تم تسجيل الدخول',
alreadyLogged: 'تم تسجيل الدخول بالفعل',
loginFailed: "تعذر تسجيل الدخول",
loginFailed: 'تعذر تسجيل الدخول',
loggedOut: 'تم تسجيل الخروج',
cancellingCurrentItem: 'جار الغاء العنصر الحالي.',
currentItemCancelled: 'تم الغاء العنصر الحالي.',
@ -208,7 +207,7 @@ const ar = {
overwriteFile: {
title: 'هل يمكنني استبدال الملفات?',
y: 'نعم, استبدال الملفات',
n: "لا, لا تبدل الملفات",
n: 'لا, لا تبدل الملفات',
t: 'استبدل العلامات فقط',
b: 'لا ، احتفظ بالملفين وأضف رقمًا إلى الملف المكرر'
},

View File

@ -43,8 +43,10 @@ const de = {
contributing: 'Du möchtest bei dem Projekt helfen? Das kannst du auf verschiedene Arten machen!',
donations: 'Du möchtest deemix finanziell unterstützen? Dann lasse eine kleine Spende da!'
},
usesLibrary: 'Dieses Programm nutzt die <strong>deemix</strong> Bibliothek, die du dazu nutzen kannst deine eigene deemix UI zu erstellen.',
thanks: 'Ein Dankeschön geht an <strong>rtonno</strong>, <strong>uhwot</strong> and <strong>lollilol</strong> für die Hilfe bei diesem Projekt und an <strong>BasCurtiz</strong> für die Erstellung des Logos.',
usesLibrary:
'Dieses Programm nutzt die <strong>deemix</strong> Bibliothek, die du dazu nutzen kannst deine eigene deemix UI zu erstellen.',
thanks:
'Ein Dankeschön geht an <strong>rtonno</strong>, <strong>uhwot</strong> and <strong>lollilol</strong> für die Hilfe bei diesem Projekt und an <strong>BasCurtiz</strong> für die Erstellung des Logos.',
upToDate: {
text: 'Bleib auf dem Laufenden mit den Updates indem du dem {newsChannel} auf Telegram folgst.',
newsChannel: 'News Channel'
@ -55,27 +57,35 @@ const de = {
officialSubreddit: 'Offizieller Subreddit',
newsChannel: 'News Channel',
questions: {
text:'Bei Fragen oder Problemen mit der App, suche als erstes nach einer Lösung im {subreddit}. Wenn du da nichts findest, kannst du einen Beitrag mit deinen Problem auf dem Subreddit verfassen.',
text:
'Bei Fragen oder Problemen mit der App, suche als erstes nach einer Lösung im {subreddit}. Wenn du da nichts findest, kannst du einen Beitrag mit deinen Problem auf dem Subreddit verfassen.',
subreddit: 'Subreddit'
},
beforeReporting: 'Bevor du einen Bug meldest, stelle sicher, dass du die neueste Version der App hast und dass das, was du melden möchtest, tatsächlich ein Bug ist und nicht nur bei dir falsch ist.',
beSure: 'Stelle sicher, dass der Bug auf anderen Computern auch vorhanden ist <strong>MELDEN NICHT</strong> einen Bug, wenn er schon gemeldet worden ist.',
beforeReporting:
'Bevor du einen Bug meldest, stelle sicher, dass du die neueste Version der App hast und dass das, was du melden möchtest, tatsächlich ein Bug ist und nicht nur bei dir falsch ist.',
beSure:
'Stelle sicher, dass der Bug auf anderen Computern auch vorhanden ist <strong>MELDEN NICHT</strong> einen Bug, wenn er schon gemeldet worden ist.',
duplicateReports: 'Doppelte Fehlerberichte werden geschlossen, achte darauf.',
dontOpenIssues: '<strong>ERSTELLE KEINE</strong> Fehlermeldungen um Fragen zu stellen, es gibt einen Subreddit dafür.',
dontOpenIssues:
'<strong>ERSTELLE KEINE</strong> Fehlermeldungen um Fragen zu stellen, es gibt einen Subreddit dafür.',
newUI: {
text: 'Wenn du Python fließend beherrschst, kannst du versuchen, mit hilfe der base library eine neue Benutzeroberfläche für die App zu erstellen oder Fehler in der Bibliothek mit einem Pull-Request in der {repo} zu beheben.',
text:
'Wenn du Python fließend beherrschst, kannst du versuchen, mit hilfe der base library eine neue Benutzeroberfläche für die App zu erstellen oder Fehler in der Bibliothek mit einem Pull-Request in der {repo} zu beheben.',
repo: 'deemix Repo'
},
acceptFeatures: 'Ich akzeptiere auch Funktionen, aber keine komplexen Dinge, da sie direkt in der App und nicht in der Bibliothek implementiert werden können.',
otherLanguages: 'Wenn du eine andere Programmiersprache fließend beherrschst, kannst du versuchen, deemix in andere Programmiersprachen zu portieren!',
acceptFeatures:
'Ich akzeptiere auch Funktionen, aber keine komplexen Dinge, da sie direkt in der App und nicht in der Bibliothek implementiert werden können.',
otherLanguages:
'Wenn du eine andere Programmiersprache fließend beherrschst, kannst du versuchen, deemix in andere Programmiersprachen zu portieren!',
understandingCode: 'Du benötigst Hilfe beim verstehen des Codes? Frag einfach RemixDev auf Telegram oder Reddit.',
contributeWebUI: {
text: 'Wenn du Vue.js (JavaScript) oder HTML und CSS kennst, könntest du etwas zum {webui} beitragen.',
webui: 'WebUI'
},
itsFree: 'Du solltest im Kopf behalten das <strong>dies ein kostenloses Projekt ist</strong> und <strong>Du solltest die Künstler unterstützen, die du magst </strong> bevor du die Entwickler unterstützt.',
itsFree:
'Du solltest im Kopf behalten das <strong>dies ein kostenloses Projekt ist</strong> und <strong>Du solltest die Künstler unterstützen, die du magst </strong> bevor du die Entwickler unterstützt.',
notObligated: 'Fühle dich nicht gezwungen zu spenden, danke, dass du deemix verwendest!',
lincensedUnder:{
lincensedUnder: {
text: 'Diese Arbeit ist lizensiert unter der {gpl3}.',
gpl3: 'GNU General Public License 3.0'
}
@ -91,7 +101,7 @@ const de = {
invalidURL: 'URL nicht erkannt',
unsupportedURL: 'URL noch nicht unterstützt',
ISRCnotOnDeezer: 'Track ISRC ist auf deezer nicht verfügbar',
notYourPrivatePlaylist: "Du kannst keine privaten Playlisten anderer herunterladen.",
notYourPrivatePlaylist: 'Du kannst keine privaten Playlisten anderer herunterladen.',
spotifyDisabled: 'Spotify-Funktionen sind nicht richtig eingerichtet',
trackNotOnDeezer: 'Track ist nicht verfügbar auf Deezer!',
albumNotOnDeezer: 'Album auf Deezer nicht gefunden!',
@ -101,8 +111,9 @@ const de = {
wrongBitrate: 'Track mit gewünschter Bitrate nicht gefunden.',
wrongBitrateNoAlternative: 'Track mit gewünschter Bitrate nicht gefunden und keine Alternative gefunden!',
no360RA: 'Track ist nicht verfügbar in Reality Audio 360.',
notAvailable: "Track ist noch nicht verfügbar auf den Servern von Deezer!",
notAvailableNoAlternative: "Track ist noch nicht verfügbar auf den Servern von Deezer und keine Alternativen gefunden!!"
notAvailable: 'Track ist noch nicht verfügbar auf den Servern von Deezer!',
notAvailableNoAlternative:
'Track ist noch nicht verfügbar auf den Servern von Deezer und keine Alternativen gefunden!!'
}
},
favorites: {
@ -121,10 +132,13 @@ const de = {
}
},
linkAnalyzer: {
info: 'Diesen Abschnitt kannst du nutzen, um weitere Informationen über den gewünschten Link zu erhalten, den du herunterladen möchtest.',
useful: "Dies ist z.B. nützlich, wenn du versuchst einige Titel herunterzuladen, welche in deinem Land nicht verfügbar sind, und du wissen möchtest, wo sie verfügbar sind.",
info:
'Diesen Abschnitt kannst du nutzen, um weitere Informationen über den gewünschten Link zu erhalten, den du herunterladen möchtest.',
useful:
'Dies ist z.B. nützlich, wenn du versuchst einige Titel herunterzuladen, welche in deinem Land nicht verfügbar sind, und du wissen möchtest, wo sie verfügbar sind.',
linkNotSupported: 'Dieser Link wird noch nicht unterstützt',
linkNotSupportedYet: 'Es scheint so, als ob dieser Link noch nicht unterstützt wird. Versuche einen anderen Link zu analysieren.',
linkNotSupportedYet:
'Es scheint so, als ob dieser Link noch nicht unterstützt wird. Versuche einen anderen Link zu analysieren.',
table: {
id: 'ID',
isrc: 'ISRC',
@ -142,7 +156,8 @@ const de = {
},
search: {
startSearching: 'Suche starten!',
description: 'Du kannst einen Titel, ein ganzes Album, einen Künstler, eine Playlist suchen ... alles! Du kannst auch einen Deezer-Link einfügen',
description:
'Du kannst einen Titel, ein ganzes Album, einen Künstler, eine Playlist suchen ... alles! Du kannst auch einen Deezer-Link einfügen',
fans: '{n} Fans',
noResults: 'Keine Ergebnisse',
noResultsTrack: 'Keine Tracks gefunden',
@ -161,7 +176,7 @@ const de = {
loggingIn: 'Einloggen',
loggedIn: 'Eingeloggt',
alreadyLogged: 'Bereits eingeloggt',
loginFailed: "Login fehlgeschlagen",
loginFailed: 'Login fehlgeschlagen',
loggedOut: 'Ausgeloggt',
cancellingCurrentItem: 'Aktuelle Auswahl abbrechen.',
currentItemCancelled: 'Aktuelle Auswahl wurde abgebrochen',
@ -228,7 +243,6 @@ const de = {
n: 'Nein überschreibe die Dateien nicht',
t: 'Überschreibe nur die Tags',
b: 'Nein, behalte beide Dateien und füge der Kopie eine Nummer hinzu'
},
fallbackBitrate: 'Falls gewünschte Bitrate nicht verfügbar, auf niedrigere Bitrate zurückgreifen',
fallbackSearch: 'Zur Suche zurückkehren, wenn der Song nicht verfügbar ist',

View File

@ -58,7 +58,8 @@ const es = {
contributing: '¿Quieres contribuir a este proyecto? ¡Puedes hacerlo de diferentes maneras!',
donations: '¿Quiere contribuir monetariamente? ¡Puedes hacer una donación!'
},
usesLibrary: 'Esta aplicación usa la biblioteca <strong>deemix</strong>, que puedes usar para hacer tu propia interfaz de usuario para deemix.',
usesLibrary:
'Esta aplicación usa la biblioteca <strong>deemix</strong>, que puedes usar para hacer tu propia interfaz de usuario para deemix.',
thanks: `Gracias a <strong>rtonno</strong>, <strong>uhwot</strong> y <strong>lollilol</strong> por ayudarme con este proyecto, a <strong>BasCurtiz</strong> por hacer el icono.`,
upToDate: {
text: `Mantente al día con las actualizaciones siguiendo el {newsChannel} en Telegram.`,
@ -73,22 +74,27 @@ const es = {
text: `Si tienes preguntas o problemas con la aplicación, busca una solución en el {subreddit} primero. Luego, si no encuentras nada puedes hacer un post con tu problema en el subreddit.`,
subreddit: 'subreddit'
},
beforeReporting: 'Antes de informar de un error asegúrese de que está ejecutando la última versión de la aplicación y que lo que quiere informar es en realidad un error y no algo que está mal sólo en su extremo.',
beSure: 'Asegúrate de que el fallo es reproducible en otras máquinas y también <strong>NO</strong> reporte un fallo si ya ha sido reportado.',
beforeReporting:
'Antes de informar de un error asegúrese de que está ejecutando la última versión de la aplicación y que lo que quiere informar es en realidad un error y no algo que está mal sólo en su extremo.',
beSure:
'Asegúrate de que el fallo es reproducible en otras máquinas y también <strong>NO</strong> reporte un fallo si ya ha sido reportado.',
duplicateReports: 'Los informes de errores duplicados se cerrarán, así que manténgase al tanto de eso.',
dontOpenIssues: '<strong>NO</strong> abra problemas para hacer preguntas, hay un subreddit para eso.',
newUI: {
text: `Si tienes fluidez en Python podrías intentar hacer una nueva interfaz de usuario para la aplicación usando la biblioteca base, o arreglar los errores de la biblioteca con una petición pull en el {repo}.`,
repo: 'repo'
},
acceptFeatures: 'También acepto características, pero no cosas complejas, ya que se pueden implementar directamente en la aplicación y no en la biblioteca.',
otherLanguages: '¡Si dominas otro lenguaje de programación podrías intentar portar Deemix a otros lenguajes de programación!',
acceptFeatures:
'También acepto características, pero no cosas complejas, ya que se pueden implementar directamente en la aplicación y no en la biblioteca.',
otherLanguages:
'¡Si dominas otro lenguaje de programación podrías intentar portar Deemix a otros lenguajes de programación!',
understandingCode: '¿Necesitas ayuda para entender el código? Sólo tienes que poner RemixDev en Telegram o Reddit.',
contributeWebUI: {
text: `Si conoces Vue.js (JavaScript), HTML o CSS podrías contribuir a la {webui}.`,
webui: 'WebUI'
},
itsFree: 'Debes recordar que <strong>este es un proyecto libre</strong> y <strong>debes apoyar a los artistas que amas</strong> antes de apoyar a los desarrolladores.',
itsFree:
'Debes recordar que <strong>este es un proyecto libre</strong> y <strong>debes apoyar a los artistas que amas</strong> antes de apoyar a los desarrolladores.',
notObligated: 'No te sientas obligado a donar, ¡te aprecio de todas formas!',
lincensedUnder: {
text: `Esta obra está autorizada bajo una {gpl3}.`,
@ -114,10 +120,12 @@ const es = {
notEncoded: '¡Pista aún no codificada!',
notEncodedNoAlternative: '¡Pista aún no codificada y no se ha encontrado ninguna alternativa!',
wrongBitrate: 'La pista no se encuentra a la velocidad de bitrate deseada.',
wrongBitrateNoAlternative: '¡Pista no encontrada a la tasa de bits deseada y no se ha encontrado ninguna alternativa!',
wrongBitrateNoAlternative:
'¡Pista no encontrada a la tasa de bits deseada y no se ha encontrado ninguna alternativa!',
no360RA: 'La pista no está disponible en Reality Audio 360.',
notAvailable: '¡La pista no está disponible en los servidores de Deezer!',
notAvailableNoAlternative: '¡La pista no está disponible en los servidores de Deezer y no se ha encontrado ninguna alternativa!',
notAvailableNoAlternative:
'¡La pista no está disponible en los servidores de Deezer y no se ha encontrado ninguna alternativa!',
noSpaceLeft: '¡No queda espacio en el dispositivo!'
}
},
@ -138,7 +146,8 @@ const es = {
},
linkAnalyzer: {
info: 'Puedes usar esta sección para encontrar más información sobre el enlace que estás tratando de descargar.',
useful: 'Esto es útil si está tratando de descargar algunas pistas que no están disponibles en su país y quiere saber dónde están disponibles, por ejemplo.',
useful:
'Esto es útil si está tratando de descargar algunas pistas que no están disponibles en su país y quiere saber dónde están disponibles, por ejemplo.',
linkNotSupported: 'Este enlace aún no está soportado',
linkNotSupportedYet: 'Parece que este enlace aún no está soportado, intenta analizar otro.',
table: {
@ -158,7 +167,8 @@ const es = {
},
search: {
startSearching: '¡Comienza a buscar!',
description: 'Puedes buscar un tema, un álbum entero, un artista, una lista de reproducción... ¡todo! También puedes pegar un enlace de Deezer',
description:
'Puedes buscar un tema, un álbum entero, un artista, una lista de reproducción... ¡todo! También puedes pegar un enlace de Deezer',
fans: '{n} fans',
noResults: 'Ningun resultado',
noResultsTrack: 'No se encontraron pistas',
@ -278,7 +288,8 @@ const es = {
jpegImageQuality: 'Calidad de la imagen JPEG',
embeddedArtworkPNG: 'Guardar las imágenes incrustadas como PNG',
embeddedPNGWarning: 'Las PNG no están oficialmente soportadas por Deezer y puedes encontrar errores.',
imageSizeWarning: 'Nada por encima de x1200 no es usado oficialmente por Deezer, puede que encuentres inconvenientes',
imageSizeWarning:
'Nada por encima de x1200 no es usado oficialmente por Deezer, puede que encuentres inconvenientes',
coverDescriptionUTF8: 'Guardar la descripción de la portada usando UTF8 (arregla la portada de iTunes)'
},
tags: {

View File

@ -39,11 +39,12 @@ const hr = {
license: 'Licenca'
},
subtitles: {
bugReports: "Postoji nešto što ne radi u deemixu? Reci nam!",
bugReports: 'Postoji nešto što ne radi u deemixu? Reci nam!',
contributing: 'Želiš doprinijeti ovom projektu? Možeš i to čak u više načina!',
donations: 'Želiš doprijeniti odmah? Možeš donirati!'
},
usesLibrary: 'Ova aplikacija koristi <strong>deemix</strong> biblioteku, koju možeš koristiti i ti kako bi napravio svoj UI za demix.',
usesLibrary:
'Ova aplikacija koristi <strong>deemix</strong> biblioteku, koju možeš koristiti i ti kako bi napravio svoj UI za demix.',
thanks: `Hvala <strong>rtonno</strong>, <strong>uhwot</strong> i <strong>lollilol</strong> što su mi pomogli s ovim projektom te <strong>BasCurtiz</strong> što su napravili ikonu.`,
upToDate: {
text: `Ostani u tijeku s nadogradnjama prateći {newsChannel} na Telegramu.`,
@ -91,7 +92,7 @@ const hr = {
invalidURL: 'URL nije prepoznat',
unsupportedURL: 'URL još nije podržan',
ISRCnotOnDeezer: 'Zapis ISRC još nije podržan na Deezeru',
notYourPrivatePlaylist: "Ne možete preuzeti tuđe privatne playliste.",
notYourPrivatePlaylist: 'Ne možete preuzeti tuđe privatne playliste.',
spotifyDisabled: 'Spotify značajke nisu podešene ispravno.',
trackNotOnDeezer: 'Pjesma nije pronađena na Deezeru!',
albumNotOnDeezer: 'Album nije pronađen na Deezeru!',
@ -101,8 +102,8 @@ const hr = {
wrongBitrate: 'Pjesma nije pronađena u željenom bitrateu.',
wrongBitrateNoAlternative: 'Pjesma nije pronađena u željenom bitrateu i nije pronađena alternativa!',
no360RA: 'Pjesma nije dostupna u Reality Audio 360.',
notAvailable: "Pjesma nije dostupna na Deezerovim serverima!",
notAvailableNoAlternative: "Pjesma nije dostupna na Deezerovim serverima i alternativa nije pronađena!"
notAvailable: 'Pjesma nije dostupna na Deezerovim serverima!',
notAvailableNoAlternative: 'Pjesma nije dostupna na Deezerovim serverima i alternativa nije pronađena!'
}
},
favorites: {
@ -123,7 +124,7 @@ const hr = {
linkAnalyzer: {
info: 'Ovu sekciju možete koristiti kako biste saznali više informacija o linku koji pokušavate preuzeti.',
useful:
"Ovo je korisno ako pokušavate preuzeti pjesme koje još nisu dostupne u vašoj zemlji i želite, na primjer, znati gdje su dostupne.",
'Ovo je korisno ako pokušavate preuzeti pjesme koje još nisu dostupne u vašoj zemlji i želite, na primjer, znati gdje su dostupne.',
linkNotSupported: 'Ovaj link još nije podržan',
linkNotSupportedYet: 'Čini se da ovaj link još nije podržan, pokušaj analizirati neki drugi.',
table: {
@ -163,7 +164,7 @@ const hr = {
loggingIn: 'Prijavljivanje...',
loggedIn: 'Prijavljeni',
alreadyLogged: 'Već prijavljeni',
loginFailed: "Prijava nije bila moguća",
loginFailed: 'Prijava nije bila moguća',
loggedOut: 'Odjavljeni',
cancellingCurrentItem: 'Otkazujem trenutnu stavku.',
currentItemCancelled: 'Trenutna stavka otkazana.',
@ -228,7 +229,7 @@ const hr = {
overwriteFile: {
title: 'Trebam li prepisati datoteke?',
y: 'Da, prepiši datoteke',
n: "Ne, nemoj prepisati datoteke",
n: 'Ne, nemoj prepisati datoteke',
t: 'Prepiši samo oznake',
b: 'Ne, zadrži obje datoteke i dodaj broj duplikatu'
},

View File

@ -39,11 +39,12 @@ const id = {
license: 'Lisensi'
},
subtitles: {
bugReports: "Ada yang tidak bekerja dengan baik di deemix? Beri tahu kami!",
bugReports: 'Ada yang tidak bekerja dengan baik di deemix? Beri tahu kami!',
contributing: 'Mau kontribusi dalam proyek ini? Kamu bisa lakukan dengan banyak hal!',
donations: 'Mau kontribusi secara finansial? Kamu bisa beri donasi!'
},
usesLibrary: 'Aplikasi ini menggunakan pustaka <strong>deemix</strong>, yang bisa kamu gunakan untuk membuat UI deemix milikmu sendiri.',
usesLibrary:
'Aplikasi ini menggunakan pustaka <strong>deemix</strong>, yang bisa kamu gunakan untuk membuat UI deemix milikmu sendiri.',
thanks: `Terima kasih kepada <strong>rtonno</strong>, <strong>uhwot</strong> dan <strong>lollilol</strong> yang telah membantuku dalam proyek ini, serta kepada <strong>BasCurtiz</strong> yang telah membuat ikon.`,
upToDate: {
text: `Ikuti {newsChannel} di Telegram agar tidak ketinggalan berita terbaru.`,
@ -91,7 +92,7 @@ const id = {
invalidURL: 'URL tidak dikenal',
unsupportedURL: 'URL belum didukung',
ISRCnotOnDeezer: 'Lagu ISRC tidak tersedia di deezer',
notYourPrivatePlaylist: "Kamu tidak bisa mengunduh daftar putar privat orang lain.",
notYourPrivatePlaylist: 'Kamu tidak bisa mengunduh daftar putar privat orang lain.',
spotifyDisabled: 'Fitur Spotify tidak diatur dengan benar.',
trackNotOnDeezer: 'Lagu tidak ditemukan di deezer!',
albumNotOnDeezer: 'Album tidak ditemukan di deezer!',
@ -101,8 +102,8 @@ const id = {
wrongBitrate: 'Lagu tidak tersedia pada bitrate yang diinginkan.',
wrongBitrateNoAlternative: 'Lagu tidak tersedia pada bitrate yang diinginkan dan tidak ada alternatif lain!',
no360RA: 'Lagu tidak tersedia pada Reality Audio 360.',
notAvailable: "Lagu tidak tersedia pada server deezer!",
notAvailableNoAlternative: "Lagu tidak tersedia pada server deezer dan tidak ada alternatif lain!"
notAvailable: 'Lagu tidak tersedia pada server deezer!',
notAvailableNoAlternative: 'Lagu tidak tersedia pada server deezer dan tidak ada alternatif lain!'
}
},
favorites: {
@ -123,7 +124,7 @@ const id = {
linkAnalyzer: {
info: 'Di sini, kamu bisa mencari informasi lebih lanjut tentang tautan yang ingin kamu unduh.',
useful:
"Contohnya, ini dapat berguna jika kamu ingin mengunduh lagu yang tidak tersedia di negaramu dan ingin tahu di negara mana lagu itu tersedia.",
'Contohnya, ini dapat berguna jika kamu ingin mengunduh lagu yang tidak tersedia di negaramu dan ingin tahu di negara mana lagu itu tersedia.',
linkNotSupported: 'Tautan seperti ini belum didukung',
linkNotSupportedYet: 'Sepertinya tautan ini belum didukung, silakan coba analisa tautan lain.',
table: {
@ -163,7 +164,7 @@ const id = {
loggingIn: 'Masuk',
loggedIn: 'Telah masuk',
alreadyLogged: 'Telah masuk',
loginFailed: "Tidak bisa masuk",
loginFailed: 'Tidak bisa masuk',
loggedOut: 'Belum masuk',
cancellingCurrentItem: 'Membatalkan item.',
currentItemCancelled: 'Item telah dibatalan.',
@ -227,7 +228,7 @@ const id = {
overwriteFile: {
title: 'Apakah file mau ditimpa?',
y: 'Ya, silakan',
n: "Tidak, jangan ditimpa",
n: 'Tidak, jangan ditimpa',
t: 'Timpa tag-nya saja'
},
fallbackBitrate: 'Rendahkan bitrate',

View File

@ -63,11 +63,12 @@ const ko = {
license: '이용정책'
},
subtitles: {
bugReports: "무언가 안되는 것이 있다고요? 말해주세요!",
bugReports: '무언가 안되는 것이 있다고요? 말해주세요!',
contributing: '이 프로젝트에 기여하고 싶다고요? 어렵지 않아요!',
donations: '금전적으로 지원하고 싶다고요? 후원하세요!'
},
usesLibrary: '이 프로그램은 <strong>deemix</strong> 라이브러리를 사용합니다, 해당 라이브러리로 자신만의 deemix를 만들 수 있습니다.',
usesLibrary:
'이 프로그램은 <strong>deemix</strong> 라이브러리를 사용합니다, 해당 라이브러리로 자신만의 deemix를 만들 수 있습니다.',
thanks: `이 프로젝트를 도와준 <strong>rtonno</strong>, <strong>uhwot</strong> 그리고 <strong>lollilol</strong>님과 아이콘을 만들어준 <strong>BasCurtiz</strong> 그리고 <strong>scarvimane</strong>님에게 감사를.`,
upToDate: {
text: `새로운 업데이트 소식을 듣고 싶으면 텔레그램 {newsChannel}을 참고하세요.`,
@ -115,7 +116,7 @@ const ko = {
unsupportedURL: 'URL 지원 누락',
invalidURL: 'URL 인식 실패',
ISRCnotOnDeezer: '트랙 코드 식별이 불가능합니다',
notYourPrivatePlaylist: "다른 사람의 비공개 재생 목록을 다운로드 할 수 없습니다.",
notYourPrivatePlaylist: '다른 사람의 비공개 재생 목록을 다운로드 할 수 없습니다.',
spotifyDisabled: '스포티파이 기능이 올바르게 설정되지 않았습니다.',
trackNotOnDeezer: 'Deezer에서 트랙을 찾을 수 없습니다!',
albumNotOnDeezer: 'Deezer에서 앨범을 찾을 수 없습니다!',
@ -125,10 +126,10 @@ const ko = {
wrongBitrate: '요구하는 비트레이트의 트랙을 찾을 수 없습니다.',
wrongBitrateNoAlternative: '요구하는 비트레이트를 찾을 수 없을 뿐더러 대체할 것을 찾지 못했습니다!',
no360RA: '해당 트랙은 360 리얼리티 오디오에 존재하지 않습니다.',
notAvailable: "해당 트랙은 Deezer 서버에 존재하지 않습니다!",
notAvailableNoAlternative: "해당 트랙은 Deezer 서버에 존재하지 않을 뿐더러 대체할 것을 찾지 못했습니다!",
noSpaceLeft: "장치에 여유 공간이 없습니다!",
albumDoesntExists: "트랙의 앨범이 존재하지 않습니다, 정보 수집에 실패했습니다."
notAvailable: '해당 트랙은 Deezer 서버에 존재하지 않습니다!',
notAvailableNoAlternative: '해당 트랙은 Deezer 서버에 존재하지 않을 뿐더러 대체할 것을 찾지 못했습니다!',
noSpaceLeft: '장치에 여유 공간이 없습니다!',
albumDoesntExists: '트랙의 앨범이 존재하지 않습니다, 정보 수집에 실패했습니다.'
}
},
favorites: {
@ -148,7 +149,7 @@ const ko = {
},
linkAnalyzer: {
info: '이 항목에서는 다운로드를 시도할 링크에 대한 더 많은 정보를 찾을 수 있습니다.',
useful: "접속한 국가에서는 재생할 수 없는 특정 트랙을 다운로드 하기 위해서 가능한 국가를 찾는데 유용하게 쓰입니다.",
useful: '접속한 국가에서는 재생할 수 없는 특정 트랙을 다운로드 하기 위해서 가능한 국가를 찾는데 유용하게 쓰입니다.',
linkNotSupported: '해당 링크는 아직 지원하지 않습니다',
linkNotSupportedYet: '해당 링크는 아직 지원하지 않습니다, 다른 링크로 시도해보세요.',
@ -192,7 +193,7 @@ const ko = {
loggingIn: '로그인 하는 중...',
loggedIn: '로그인 되었습니다',
alreadyLogged: '이미 로그인되어 있습니다',
loginFailed: "로그인 할 수 없습니다",
loginFailed: '로그인 할 수 없습니다',
loggedOut: '로그아웃 하였습니다',
cancellingCurrentItem: '현재 항목을 취소 중입니다.',
currentItemCancelled: '항목이 취소되었습니다.',
@ -265,10 +266,10 @@ const ko = {
overwriteFile: {
title: '파일을 덮어쓸까요?',
y: '네, 파일을 덮어쓰세요',
n: "아뇨, 파일을 덮어쓰지 마세요",
n: '아뇨, 파일을 덮어쓰지 마세요',
t: '태그만 덮어쓰세요',
b: '아뇨, 양쪽 다 놔두고 중복되는 파일에 번호를 추가하세요',
e: "아뇨, 확장명을 변경하세요"
e: '아뇨, 확장명을 변경하세요'
},
fallbackBitrate: '비트레이트 대비책',
fallbackSearch: '검색 대비책',

View File

@ -55,11 +55,12 @@ const ph = {
license: 'Lisensiya'
},
subtitles: {
bugReports: "Meron bang hindi gumagana sa deemix? Ipaalam mo sa amin!",
bugReports: 'Meron bang hindi gumagana sa deemix? Ipaalam mo sa amin!',
contributing: 'Gusto mo bang tumulong sa proyektong ito? Pwede mong gawin iyan sa maraming paraan!',
donations: 'Gusto mo bang tumulong sa pamamagitan ng pera? Pwede kang magbigay ng donasiyon!'
},
usesLibrary: 'Ang app na ito ay gumagamit ng library galing sa <strong>deemix</strong>, na kung saan ay pwede mong gamitin para gumawa ng sarili mong UI ng deemix.',
usesLibrary:
'Ang app na ito ay gumagamit ng library galing sa <strong>deemix</strong>, na kung saan ay pwede mong gamitin para gumawa ng sarili mong UI ng deemix.',
thanks: `Salamat kay <strong>rtonno</strong>, <strong>uhwot</strong> at <strong>lollilol</strong> sa pagtulong sa akin para sa proyektong ito at kay <strong>BasCurtiz</strong> sa paggawa ng icon.`,
upToDate: {
text: `Huwag magpapahuli sa mga update patungkol dito sa pamamagitan ng pagsali sa {newsChannel} sa Telegram.`,
@ -107,7 +108,7 @@ const ph = {
invalidURL: 'Hindi makilala ang URL',
unsupportedURL: 'Hindi pa suportado ang URL',
ISRCnotOnDeezer: 'Ang Track ISRC ay hindi pwede sa Deezer',
notYourPrivatePlaylist: "Hindi pwedeng i-download ang mga pribadong playlist ng iba.",
notYourPrivatePlaylist: 'Hindi pwedeng i-download ang mga pribadong playlist ng iba.',
spotifyDisabled: 'Hindi mo nai-set nang tama ang Spotify Features.',
trackNotOnDeezer: 'Hindi mahanap ang track sa Deezer!',
albumNotOnDeezer: 'Hindi mahanap ang album sa Deezer!',
@ -117,9 +118,9 @@ const ph = {
wrongBitrate: 'Hindi mahanap ang track sa gusto mong bitrate.',
wrongBitrateNoAlternative: 'Hindi mahanap ang track sa gusto mong bitrate at walang mahanap na iba!',
no360RA: 'Hindi pwede ang track para sa Reality Audio 360.',
notAvailable: "Walang available na track sa server ng Deezer!",
notAvailableNoAlternative: "Walang available na track sa server ng Deezer at walang mahanap na iba!",
noSpaceLeft: "Wala nang natitirang space sa iyong device!"
notAvailable: 'Walang available na track sa server ng Deezer!',
notAvailableNoAlternative: 'Walang available na track sa server ng Deezer at walang mahanap na iba!',
noSpaceLeft: 'Wala nang natitirang space sa iyong device!'
}
},
favorites: {
@ -139,7 +140,8 @@ const ph = {
},
linkAnalyzer: {
info: 'Pwede gamitin ang section na ito para sa iba pang impormasyon patungkol sa link na gusto mong i-download.',
useful: "Makatutulong ito kung meron kang gustong i-download na track na hindi available sa bansa mo at gusto mong malaman kung meron bang ganito kapag sa iba.",
useful:
'Makatutulong ito kung meron kang gustong i-download na track na hindi available sa bansa mo at gusto mong malaman kung meron bang ganito kapag sa iba.',
linkNotSupported: 'Hindi pa suportado ang link',
linkNotSupportedYet: 'Mukhang hindi pa suportado itong link, iba na lang ang ilagay mo.',
table: {
@ -159,7 +161,8 @@ const ph = {
},
search: {
startSearching: 'Simulang Maghanap!',
description: 'Pwede kang maghanap ng track, buong album, artist, playlist.... kahit ano! Pwede ka ring mag-paste dito ng link na galing sa Deezer',
description:
'Pwede kang maghanap ng track, buong album, artist, playlist.... kahit ano! Pwede ka ring mag-paste dito ng link na galing sa Deezer',
fans: '{n} mga fan',
noResults: 'Walang resulta',
noResultsTrack: 'Walang mahanap na mga Track',
@ -181,7 +184,7 @@ const ph = {
loggingIn: 'Nagla-log in...',
loggedIn: 'Na-login na',
alreadyLogged: 'Nakalogin ka na',
loginFailed: "Hindi maka-log in",
loginFailed: 'Hindi maka-log in',
loggedOut: 'Na-logout na',
cancellingCurrentItem: 'Kinakansel ang item.',
currentItemCancelled: 'Nakansel na ang item.',
@ -248,10 +251,10 @@ const ph = {
overwriteFile: {
title: 'Papatungan ko ba ang file?',
y: 'Oo, patungan mo ang file',
n: "Hindi, huwag mong patungan ang file",
n: 'Hindi, huwag mong patungan ang file',
t: 'Patungan mo lang ang mga tag',
b: 'Hindi, hayaan mo silang dalawa at lagyan mo lang ng numero sa kapareho niya',
e: "Hindi, at huwag mong tignan ang mga extension"
e: 'Hindi, at huwag mong tignan ang mga extension'
},
fallbackBitrate: 'Binabaang bitrate',
fallbackSearch: 'Maghanap para sa binabaan',
@ -279,7 +282,8 @@ const ph = {
jpegImageQuality: 'Kalidad ng JPEG na imahe',
embeddedArtworkPNG: 'I-save ang nakadikit na artwork bilang PNG',
embeddedPNGWarning: 'Ang mga PNG ay hindi opisyal na suportado ng Deezer at maaaring magkaroon ng bug',
imageSizeWarning: 'Lahat ng mas mataas sa x1200 ay hindi opisyal na ginagamit sa Deezer, at posibleng magkaroon ng isyu',
imageSizeWarning:
'Lahat ng mas mataas sa x1200 ay hindi opisyal na ginagamit sa Deezer, at posibleng magkaroon ng isyu',
coverDescriptionUTF8: 'I-save ang deskripsyon ng cover gamit ng UTF8 (iTunes Cover Fix)'
},
tags: {

View File

@ -55,11 +55,12 @@ const pl = {
license: 'Licencja'
},
subtitles: {
bugReports: "Czy deemix działa inaczej niż powinien? Powiedz nam!",
bugReports: 'Czy deemix działa inaczej niż powinien? Powiedz nam!',
contributing: 'Chcesz pomóc w tym projekcie? Możesz to zrobić na wiele sposobów!',
donations: 'Chcesz pomóc finansowo? Możesz nas wesprzeć!'
},
usesLibrary: 'Ten program używa biblioteki <strong>deemix</strong>, której możesz użyć do stworzenia własnego interfejsu użytkownika',
usesLibrary:
'Ten program używa biblioteki <strong>deemix</strong>, której możesz użyć do stworzenia własnego interfejsu użytkownika',
thanks: `Podziękowania dla <strong>rtonno</strong>, <strong>uhwot</strong> i <strong>lollilol</strong> za pomoc w tym projekcie oraz dla <strong>BasCurtiz</strong> za stworzenie ikony.`,
upToDate: {
text: `Bądź na bieżąco z aktualizacjami dołączając do {newsChannel} na Telegramie.`,
@ -107,7 +108,7 @@ const pl = {
invalidURL: 'Nierozpoznany URL',
unsupportedURL: 'Niewspierany URL',
ISRCnotOnDeezer: 'ISRC nie jest dostępne na Deezerze',
notYourPrivatePlaylist: "Nie możesz pobierać czyichś prywatnych playlist.",
notYourPrivatePlaylist: 'Nie możesz pobierać czyichś prywatnych playlist.',
spotifyDisabled: 'Funkcje Spotify nie są poprawnie ustawione',
trackNotOnDeezer: 'Nie znaleziono utworu na Deezerze!',
albumNotOnDeezer: 'Nie znaleziono albumu na Deezerze!',
@ -117,8 +118,8 @@ const pl = {
wrongBitrate: 'Nie znaleziono utworu w wybranym bitrate.',
wrongBitrateNoAlternative: 'Nie znaleziono utworu w wybranym bitrate i nie mozna znaleźć alternatywy!',
no360RA: 'Utwór nie jest dostępny w Reality Audio 360.',
notAvailable: "Utwór nie jest dostępny na serwerach Deezera!",
notAvailableNoAlternative: "Utwór nie jest dostępny na serwerach Deezera i nie można znaleźć alternatywy!"
notAvailable: 'Utwór nie jest dostępny na serwerach Deezera!',
notAvailableNoAlternative: 'Utwór nie jest dostępny na serwerach Deezera i nie można znaleźć alternatywy!'
}
},
favorites: {
@ -138,7 +139,8 @@ const pl = {
},
linkAnalyzer: {
info: 'Możesz użyć tej sekcji, aby znaleźć więcej informacji o linku, który chcesz pobrać.',
useful: "Jest to przydatne na przykład gdy chcesz pobrać jakieś utwory, które nie są dostępne w twoim kraju i chcesz wiedzieć gdzie są dostępne.",
useful:
'Jest to przydatne na przykład gdy chcesz pobrać jakieś utwory, które nie są dostępne w twoim kraju i chcesz wiedzieć gdzie są dostępne.',
linkNotSupported: 'Ten link nie jest jeszcze wspierany',
linkNotSupportedYet: 'Wygląda na to, że ten link nie jest jeszcze wspierany. Spróbuj przeanalizować inny.',
table: {
@ -180,7 +182,7 @@ const pl = {
loggingIn: 'Logowanie...',
loggedIn: 'Zalogowano',
alreadyLogged: 'Już zalogowano',
loginFailed: "Nie można zalogować",
loginFailed: 'Nie można zalogować',
loggedOut: 'Wylogowano',
cancellingCurrentItem: 'Anulowanie przedmiotu.',
currentItemCancelled: 'Anulowano przedmiot.',
@ -246,7 +248,7 @@ const pl = {
overwriteFile: {
title: 'Nadpisywać pliki?',
y: 'Tak',
n: "Nie",
n: 'Nie',
t: 'Tylko tagi',
b: 'Nie, dodaj numer do drugiego pliku',
e: 'Nie, nie patrz na rozszerzenia'

View File

@ -43,7 +43,8 @@ const pt = {
contributing: 'Queres contribuir para o projecto? Podes fazê-lo de diferentes formas!',
donations: 'Desejas contribuir monetariamente? Faz uma doação!'
},
usesLibrary: 'Esta aplicação usa a biblioteca <strong>deemix</strong>, que poderás usar para desenvolver o teu proprio UI para o deemix.',
usesLibrary:
'Esta aplicação usa a biblioteca <strong>deemix</strong>, que poderás usar para desenvolver o teu proprio UI para o deemix.',
thanks: `Agradeço a <strong>rtonno</strong>, <strong>uhwot</strong> and <strong>lollilol</strong> por me ajudarem neste projeto e a <strong>BasCurtiz</strong> por elaborarem o ícone.`,
upToDate: {
text: `Mantem-te atualizado seguindo o {newsChannel} no Telegram.`,
@ -91,7 +92,7 @@ const pt = {
invalidURL: 'URL não reconhecido',
unsupportedURL: 'URL ainda não suportado',
ISRCnotOnDeezer: 'Faixa ISRC não disponível no deezer',
notYourPrivatePlaylist: "Nao podes baixar listas de reprodução privadas de outros.",
notYourPrivatePlaylist: 'Nao podes baixar listas de reprodução privadas de outros.',
spotifyDisabled: 'Funcionalidades do Spotify não estão definidas corretamente.',
trackNotOnDeezer: 'Faixa não encontrada no deezer!',
albumNotOnDeezer: 'Álbum não encontrado no deezer!',
@ -122,7 +123,8 @@ const pt = {
},
linkAnalyzer: {
info: 'Podes usar esta secção para obteres mais informação sobre o link que estás a tentar transferir.',
useful: 'Isto é útil caso estejas a tentar transferir faixas que não estão disponíveis no teu país e queres saber onde estão disponíveis, por exemplo.',
useful:
'Isto é útil caso estejas a tentar transferir faixas que não estão disponíveis no teu país e queres saber onde estão disponíveis, por exemplo.',
linkNotSupported: 'Este link ainda não é suportado',
linkNotSupportedYet: 'Parece que este link ainda não é suportado, tenta analisar outro.',
table: {
@ -142,7 +144,8 @@ const pt = {
},
search: {
startSearching: 'Começa a pesquisar!',
description: 'Podes perquisar uma música, um álbum inteiro, um artista, uma lista de reprodução... tudo! Também podes colar um link do Deezer',
description:
'Podes perquisar uma música, um álbum inteiro, um artista, uma lista de reprodução... tudo! Também podes colar um link do Deezer',
fans: '{n} fãs',
noResults: 'Sem resultados',
noResultsTrack: 'Faixa não encontrada',
@ -161,7 +164,7 @@ const pt = {
loggingIn: 'A autenticar',
loggedIn: 'Autenticado',
alreadyLogged: 'Já estás autenticado',
loginFailed: "Nao foi possivel iniciar sessão",
loginFailed: 'Nao foi possivel iniciar sessão',
loggedOut: 'Desconectado',
cancellingCurrentItem: 'A cancelar item actual.',
currentItemCancelled: 'Item actual cancelado.',

View File

@ -58,11 +58,12 @@ const ru = {
license: 'Лицензия'
},
subtitles: {
bugReports: "Что-то не работает? Сообщите нам!",
bugReports: 'Что-то не работает? Сообщите нам!',
contributing: 'Хотите внести вклад в развитие этого проекта? Это можно сделать разными способами!',
donations: 'Хотите поддержать материально? Можно сделать пожертвование!'
},
usesLibrary: 'Приложение использует библиотеку <strong>deemix</strong>, с помощью которой вы можете разработать собственный UI для deemix.',
usesLibrary:
'Приложение использует библиотеку <strong>deemix</strong>, с помощью которой вы можете разработать собственный UI для deemix.',
thanks: `Спасибо <strong>rtonno</strong>, <strong>uhwot</strong> и <strong>lollilol</strong> за помощь с этим проектом, а также <strong>BasCurtiz</strong> за иконку.`,
upToDate: {
text: `Следите за последними обновлениями на {newsChannel} в Telegram.`,
@ -110,7 +111,7 @@ const ru = {
invalidURL: 'URL не распознан',
unsupportedURL: 'URL не поддерживается',
ISRCnotOnDeezer: 'ISRC данного трека недоступен на Deezer',
notYourPrivatePlaylist: "Вы не можете скачивать чужие приватные плейлисты.",
notYourPrivatePlaylist: 'Вы не можете скачивать чужие приватные плейлисты.',
spotifyDisabled: 'Неправильно настроены параметры Spotify.',
trackNotOnDeezer: 'Трек не найден на Deezer!',
albumNotOnDeezer: 'Альбом не найден на Deezer!',
@ -120,10 +121,10 @@ const ru = {
wrongBitrate: 'Данного трека нет в нужном битрейте.',
wrongBitrateNoAlternative: 'Данного трека нет в нужном битрейте. Альтернатив не найдено!',
no360RA: 'Трек недоступен в формате Reality Audio 360.',
notAvailable: "Трек недоступен на серверах Deezer!",
notAvailableNoAlternative: "Трек недоступен на серверах Deezer. Альтернатив не найдено!",
noSpaceLeft: "На устройстве не осталось свободного места!",
albumDoesntExists: "Альбома не существует, информация не получена"
notAvailable: 'Трек недоступен на серверах Deezer!',
notAvailableNoAlternative: 'Трек недоступен на серверах Deezer. Альтернатив не найдено!',
noSpaceLeft: 'На устройстве не осталось свободного места!',
albumDoesntExists: 'Альбома не существует, информация не получена'
}
},
favorites: {
@ -143,7 +144,8 @@ const ru = {
},
linkAnalyzer: {
info: 'Используйте этот раздел, чтобы узнать информацию о ссылке, которую требуется скачать.',
useful: "Этот раздел нужен, если вы хотите загрузить треки, недоступные в вашей стране, а также посмотреть, где они доступны.",
useful:
'Этот раздел нужен, если вы хотите загрузить треки, недоступные в вашей стране, а также посмотреть, где они доступны.',
linkNotSupported: 'Ссылка не поддерживается',
linkNotSupportedYet: 'Эта ссылка не поддерживается, попробуйте вставить другую.',
table: {
@ -185,7 +187,7 @@ const ru = {
loggingIn: 'Вход...',
loggedIn: 'Вход выполнен',
alreadyLogged: 'Вход уже выполнен',
loginFailed: "Вход не выполнен",
loginFailed: 'Вход не выполнен',
loggedOut: 'Вы вышли из аккаунта',
cancellingCurrentItem: 'Отмена текущей загрузки.',
currentItemCancelled: 'Отменено.',
@ -255,10 +257,10 @@ const ru = {
overwriteFile: {
title: 'Нужно ли перезаписывать файлы?',
y: 'Да, перезаписать файл',
n: "Нет, не перезаписывать",
n: 'Нет, не перезаписывать',
t: 'Обновить только теги',
b: 'Нет, оставить оба файла и добавить номер к дубликату',
e: "Нет, вне зависимости от расширения"
e: 'Нет, вне зависимости от расширения'
},
fallbackBitrate: 'Загружать с битрейтом ниже, если текущий недоступен',
fallbackSearch: 'Искать похожий трек, если запрашиваемый недоступен',

View File

@ -39,11 +39,12 @@ const vn = {
license: 'Bằng phép'
},
subtitles: {
bugReports: "Bạn thấy có gì đó không hoạt động trong deemix? Xin hãy báo với chúng tôi!",
bugReports: 'Bạn thấy có gì đó không hoạt động trong deemix? Xin hãy báo với chúng tôi!',
contributing: 'Bạn muốn đóng góp cho dự án này? Bạn có thể làm điều đó với nhiều cách khác nhau!',
donations: 'Bạn muốn ủng hộ kinh phí? Bạn có thể quyên góp tại đây!'
},
usesLibrary: 'Ứng dụng này sử dụng thư viện <strong>deemix</strong>, bạn có thể dùng nó để tạo một UI riêng cho deemix.',
usesLibrary:
'Ứng dụng này sử dụng thư viện <strong>deemix</strong>, bạn có thể dùng nó để tạo một UI riêng cho deemix.',
thanks: `Cảm ơn <strong>rtonno</strong>, <strong>uhwot</strong> và <strong>lollilol</strong> đã giúp tôi với dự án này và <strong>BasCurtiz</strong> với việc thiết kế biểu tượng.`,
upToDate: {
text: `Cập nhật app bằng cách theo dõi {newsChannel} trên Telegram.`,
@ -91,7 +92,7 @@ const vn = {
invalidURL: 'Không nhận diện được URL',
unsupportedURL: 'URL này chưa được hỗ trợ',
ISRCnotOnDeezer: 'ISRC của bài hát này hiện không có trên Deezer',
notYourPrivatePlaylist: "Bạn không thể tải xuống playlist riêng của người khác.",
notYourPrivatePlaylist: 'Bạn không thể tải xuống playlist riêng của người khác.',
spotifyDisabled: 'Chức năng Spotify chưa được thiết lập đúng cách.',
trackNotOnDeezer: 'Bài hát không có trên Deezer!',
albumNotOnDeezer: 'Album không có trên Deezer!',
@ -101,8 +102,8 @@ const vn = {
wrongBitrate: 'Bài hát này không có ở bitrate bạn muốn.',
wrongBitrateNoAlternative: 'Bài hát này không có ở bitrate bạn muốn và không có bản thay thế nào khác!',
no360RA: 'Bài hát này không có ở dạng Reality Audio 360.',
notAvailable: "Bài hát này không có trên server của Deezer!",
notAvailableNoAlternative: "Bài hát này không có trên server của Deezer và không có bản thay thế nào khác!"
notAvailable: 'Bài hát này không có trên server của Deezer!',
notAvailableNoAlternative: 'Bài hát này không có trên server của Deezer và không có bản thay thế nào khác!'
}
},
favorites: {
@ -123,7 +124,7 @@ const vn = {
linkAnalyzer: {
info: 'Bạn có thể sử dụng chức năng này để kiếm thêm thông tin về đường link mà bạn muốn tải xuống.',
useful:
"Chức năng này rất hữu dụng nếu bạn muốn tải các bài hát hiện không có sẵn ở quốc gia của bạn và muốn biết các quốc gia được hỗ trợ.",
'Chức năng này rất hữu dụng nếu bạn muốn tải các bài hát hiện không có sẵn ở quốc gia của bạn và muốn biết các quốc gia được hỗ trợ.',
linkNotSupported: 'Đường link này chưa được hỗ trợ',
linkNotSupportedYet: 'Đường link này chưa được hỗ trợ, xin hãy thử lại với một đường link khác.',
table: {
@ -143,8 +144,7 @@ const vn = {
},
search: {
startSearching: 'Bắt đầu tìm kiếm!',
description:
'Bạn có thể tìm một bài hát, album, nghệ sĩ, playlist, v.v...! Bạn cũng có thể dùng link của Deezer',
description: 'Bạn có thể tìm một bài hát, album, nghệ sĩ, playlist, v.v...! Bạn cũng có thể dùng link của Deezer',
fans: '{n} người hâm mộ',
noResults: 'Không có kết quả',
noResultsTrack: 'Không tìm được bài hát nào',
@ -163,7 +163,7 @@ const vn = {
loggingIn: 'Đang đăng nhập',
loggedIn: 'Đăng nhập thành công',
alreadyLogged: 'Đã đăng nhập',
loginFailed: "Không thể đăng nhập",
loginFailed: 'Không thể đăng nhập',
loggedOut: 'Đăng xuất',
cancellingCurrentItem: 'Đang hủy file hiện tại.',
currentItemCancelled: 'File hiện tại đã bị hủy.',
@ -228,7 +228,7 @@ const vn = {
overwriteFile: {
title: 'Tôi có nên ghi đè file này không?',
y: 'Có, hãy ghi đè file này',
n: "Không, đừng ghi đè file này",
n: 'Không, đừng ghi đè file này',
t: 'Chỉ ghi đè các tag'
},
fallbackBitrate: 'Bitrate dự phòng',

View File

@ -63,7 +63,7 @@ const zh_tw = {
license: '使用許可'
},
subtitles: {
bugReports: "使用 deemix 時,遇到了什麼問題嗎?歡迎回報錯誤!",
bugReports: '使用 deemix 時,遇到了什麼問題嗎?歡迎回報錯誤!',
contributing: '您想替這個專案提出貢獻嗎?您可以透過許多不同的方式來幫忙!',
donations: '您想要捐款嗎?可以贊助我們!'
},
@ -115,7 +115,7 @@ const zh_tw = {
invalidURL: '無法識別網址',
unsupportedURL: '尚不支持此網址',
ISRCnotOnDeezer: '無法在 Deezer 上使用單曲 ISRC',
notYourPrivatePlaylist: "您無法下載他人的私人播放清單。",
notYourPrivatePlaylist: '您無法下載他人的私人播放清單。',
spotifyDisabled: 'Spotify 功能未正確設定。',
trackNotOnDeezer: '在 Deezer 上找不到此歌曲!',
albumNotOnDeezer: '在 Deezer 上找不到此專輯!',
@ -125,10 +125,10 @@ const zh_tw = {
wrongBitrate: '找不到符合所設位元率的歌曲。',
wrongBitrateNoAlternative: '找不到符合所設位元率的歌曲,且無法找到其他替代歌曲!',
no360RA: '本歌曲並不支援 Reality Audio 360。',
notAvailable: "無法在 Deezer 伺服器載入此歌曲!",
notAvailableNoAlternative: "無法在 Deezer 伺服器載入此歌曲,且無法找到其他替代歌曲!",
noSpaceLeft: "本裝置可用空間已用盡!",
albumDoesntExists: "本歌曲的專輯不存在,無法取得資訊"
notAvailable: '無法在 Deezer 伺服器載入此歌曲!',
notAvailableNoAlternative: '無法在 Deezer 伺服器載入此歌曲,且無法找到其他替代歌曲!',
noSpaceLeft: '本裝置可用空間已用盡!',
albumDoesntExists: '本歌曲的專輯不存在,無法取得資訊'
}
},
favorites: {
@ -148,8 +148,7 @@ const zh_tw = {
},
linkAnalyzer: {
info: '您可以透過此工具取得您所想下載的連結的相關資訊。',
useful:
"比如,當您所想下載的歌曲無法在您的國家播放,且您想知道哪些國家可以播放此歌曲時,您可使用此工具。",
useful: '比如,當您所想下載的歌曲無法在您的國家播放,且您想知道哪些國家可以播放此歌曲時,您可使用此工具。',
linkNotSupported: '尚未支援此連結',
linkNotSupportedYet: '我們似乎尚未支援此連結,請改用其他連結。',
table: {
@ -169,8 +168,7 @@ const zh_tw = {
},
search: {
startSearching: '開始搜尋!',
description:
'您可以搜索歌曲名稱、專輯、藝人、播放清單...等等。您也可以直接貼上 Deezer 網址。',
description: '您可以搜索歌曲名稱、專輯、藝人、播放清單...等等。您也可以直接貼上 Deezer 網址。',
fans: '{n} 個粉絲',
noResults: '無搜尋結果',
noResultsTrack: '找不到歌曲',
@ -192,7 +190,7 @@ const zh_tw = {
loggingIn: '登入中...',
loggedIn: '登入',
alreadyLogged: '已登入',
loginFailed: "無法登入",
loginFailed: '無法登入',
loggedOut: '登出',
cancellingCurrentItem: '取消當前項目。',
currentItemCancelled: '當前項目已取消。',
@ -262,10 +260,10 @@ const zh_tw = {
overwriteFile: {
title: '是否要覆蓋檔案?',
y: '是,覆蓋檔案',
n: "否,請勿覆蓋檔案",
n: '否,請勿覆蓋檔案',
t: '僅覆蓋標籤',
b: '否,保留兩個檔案並在重複的檔名中加入一個數字',
e: "否,不顧慮附檔名"
e: '否,不顧慮附檔名'
},
fallbackBitrate: '當偏好位元率無法下載時,下載其他版本',
fallbackSearch: '當搜尋結果無法使用時,使用其他搜尋結果',

View File

@ -20,9 +20,9 @@ const i18n = new VueI18n({
* @param {number} choicesLength An overall amount of available choices
* @returns A final choice index to select plural word by
*/
ru: function(choice, choicesLength) {
var n = Math.abs(choice) % 100
var n1 = n % 10
ru(choice, choicesLength) {
const n = Math.abs(choice) % 100
const n1 = n % 10
if (n > 10 && n < 20) {
return 2

View File

@ -80,7 +80,7 @@ const mutations = {
},
RESET_LOGIN(state) {
// Needed for reactivity
let clientMode = state.clientMode
const clientMode = state.clientMode
Object.assign(state, getDefaultState())
state.clientMode = clientMode
}

View File

@ -5,7 +5,7 @@ export function fetchData(key, data = {}, method = 'GET') {
url.searchParams.append(key, data[key])
})
return fetch(url.href, {method})
return fetch(url.href, { method })
.then(response => response.json())
.catch(() => {})
}

View File

@ -1,6 +1,6 @@
export const COUNTRIES = {
AF: 'Afghanistan',
AX: '\u00c5land Islands',
AX: '\u00C5land Islands',
AL: 'Albania',
DZ: 'Algeria',
AS: 'American Samoa',
@ -53,10 +53,10 @@ export const COUNTRIES = {
CD: 'Congo, the Democratic Republic of the',
CK: 'Cook Islands',
CR: 'Costa Rica',
CI: "C\u00f4te d'Ivoire",
CI: "C\u00F4te d'Ivoire",
HR: 'Croatia',
CU: 'Cuba',
CW: 'Cura\u00e7ao',
CW: 'Cura\u00E7ao',
CY: 'Cyprus',
CZ: 'Czech Republic',
DK: 'Denmark',
@ -179,11 +179,11 @@ export const COUNTRIES = {
PT: 'Portugal',
PR: 'Puerto Rico',
QA: 'Qatar',
RE: 'R\u00e9union',
RE: 'R\u00E9union',
RO: 'Romania',
RU: 'Russian Federation',
RW: 'Rwanda',
BL: 'Saint Barth\u00e9lemy',
BL: 'Saint Barth\u00E9lemy',
SH: 'Saint Helena, Ascension and Tristan da Cunha',
KN: 'Saint Kitts and Nevis',
LC: 'Saint Lucia',

View File

@ -4,7 +4,7 @@
* therefore it's considered a new release, if referring to a track or album
*/
export function checkNewRelease(dateToCheck) {
let now = new Date()
const now = new Date()
now.setHours(0, 0, 0, 0)
dateToCheck = new Date(dateToCheck)

View File

@ -11,7 +11,7 @@ export function sendAddToQueue(url, bitrate = null) {
}
export function aggregateDownloadLinks(releases) {
let links = []
const links = []
releases.forEach(release => {
links.push(release.link)

View File

@ -3,13 +3,15 @@ class CustomSocket extends WebSocket {
super(args)
this.listeners = {}
}
emit(key, data) {
if (this.readyState !== WebSocket.OPEN) return false
this.send(JSON.stringify({ key, data }))
}
on(key, cb) {
if (Object.keys(this.listeners).indexOf(key) == -1){
if (!Object.keys(this.listeners).includes(key)) {
console.log('on:', key)
this.listeners[key] = cb
@ -21,10 +23,10 @@ class CustomSocket extends WebSocket {
}
})
}
}
off(key) {
if (Object.keys(this.listeners).indexOf(key) != -1){
if (Object.keys(this.listeners).includes(key)) {
console.log('off:', key)
this.removeEventListener('message', this.listeners[key])
delete this.listeners[key]

View File

@ -9,13 +9,13 @@ const sharedOptions = {
position: 'left'
}
let toastsWithId = {}
const toastsWithId = {}
export const toast = function(msg, icon = null, dismiss = true, id = null) {
export const toast = function (msg, icon = null, dismiss = true, id = null) {
if (toastsWithId[id]) {
let toastObj = toastsWithId[id]
const toastObj = toastsWithId[id]
let toastElement = document.querySelectorAll(`div.toastify[toast_id=${id}]`)
const toastElement = document.querySelectorAll(`div.toastify[toast_id=${id}]`)
if (msg) {
toastElement.forEach(toast => {
@ -28,15 +28,15 @@ export const toast = function(msg, icon = null, dismiss = true, id = null) {
}
if (icon) {
let iconNode = document.createElement('span')
const iconNode = document.createElement('span')
iconNode.classList.add('toast-icon')
if (icon == 'loading') {
let loader = document.createElement('div')
const loader = document.createElement('div')
loader.classList.add('circle-loader')
iconNode.appendChild(loader)
} else {
let materialIcon = document.createElement('i')
const materialIcon = document.createElement('i')
materialIcon.classList.add('material-icons')
materialIcon.appendChild(document.createTextNode(icon))
iconNode.appendChild(materialIcon)
@ -62,41 +62,41 @@ export const toast = function(msg, icon = null, dismiss = true, id = null) {
}, 3000)
}
} else {
let iconNode = document.createElement('span')
const iconNode = document.createElement('span')
iconNode.classList.add('toast-icon')
if (icon == null) {
iconNode.appendChild(document.createTextNode(''))
} else if (icon == 'loading') {
let loader = document.createElement('div')
const loader = document.createElement('div')
loader.classList.add('circle-loader')
iconNode.appendChild(loader)
} else {
let materialIcon = document.createElement('i')
const materialIcon = document.createElement('i')
materialIcon.classList.add('material-icons')
materialIcon.appendChild(document.createTextNode(icon))
iconNode.appendChild(materialIcon)
}
let messageNode = document.createElement('span')
const messageNode = document.createElement('span')
messageNode.classList.add('toast-message')
messageNode.appendChild(document.createTextNode(msg))
let toastNode = document.createElement('toast')
const toastNode = document.createElement('toast')
toastNode.appendChild(iconNode)
toastNode.appendChild(messageNode)
let toastObj = Toastify({
const toastObj = Toastify({
...sharedOptions,
node: toastNode,
duration: dismiss ? 3000 : 0,
className: dismiss ? 'dismissable' : '',
onClick: function() {
onClick() {
let dismissable = true
if (id) {
let toastClasses = document.querySelector(`div.toastify[toast_id=${id}]`).classList
const toastClasses = document.querySelector(`div.toastify[toast_id=${id}]`).classList
if (toastClasses) {
dismissable = Array.prototype.slice.call(toastClasses).indexOf('dismissable') != -1
dismissable = Array.prototype.slice.call(toastClasses).includes('dismissable')
}
}
if (toastObj && dismissable) {
@ -108,7 +108,7 @@ export const toast = function(msg, icon = null, dismiss = true, id = null) {
}
},
offset: {
x: 'true' === localStorage.getItem('slimSidebar') ? '3rem': '14rem'
x: localStorage.getItem('slimSidebar') === 'true' ? '3rem' : '14rem'
}
}).showToast()
if (id) {

View File

@ -8,7 +8,7 @@ export function generatePath(el) {
throw new Error('No element passed to the generatePath function!')
}
let path = [el]
const path = [el]
while ((el = el.parentNode) && el !== document) {
path.push(el)
@ -18,14 +18,14 @@ export function generatePath(el) {
}
export function isValidURL(text) {
let lowerCaseText = text.toLowerCase()
const lowerCaseText = text.toLowerCase()
if (lowerCaseText.startsWith('http')) {
if (
lowerCaseText.indexOf('deezer.com') >= 0 ||
lowerCaseText.indexOf('deezer.page.link') >= 0 ||
lowerCaseText.indexOf('open.spotify.com') >= 0 ||
lowerCaseText.indexOf('link.tospotify.com') >= 0
lowerCaseText.includes('deezer.com') ||
lowerCaseText.includes('deezer.page.link') ||
lowerCaseText.includes('open.spotify.com') ||
lowerCaseText.includes('link.tospotify.com')
) {
return true
}
@ -63,15 +63,15 @@ export function numberWithDots(x) {
// On scroll event, returns currentTarget = null
// Probably on other events too
export function debounce(func, wait, immediate) {
var timeout
return function() {
var context = this
var args = arguments
var later = function() {
let timeout
return function () {
const context = this
const args = arguments
const later = function () {
timeout = null
if (!immediate) func.apply(context, args)
}
var callNow = immediate && !timeout
const callNow = immediate && !timeout
clearTimeout(timeout)
timeout = setTimeout(later, wait)
if (callNow) func.apply(context, args)
@ -104,10 +104,10 @@ export function copyToClipboard(text) {
export function getPropertyWithFallback(obj, ...props) {
for (const prop of props) {
// Example: this.is.an.example
let hasDotNotation = /\./.test(prop)
const hasDotNotation = /\./.test(prop)
// Searching the properties in the object
let valueToTest = hasDotNotation
const valueToTest = hasDotNotation
? prop.split('.').reduce((o, i) => {
if (o) {
return o[i]
@ -115,7 +115,7 @@ export function getPropertyWithFallback(obj, ...props) {
}, obj)
: obj[prop]
if ('undefined' !== typeof valueToTest) {
if (typeof valueToTest !== 'undefined') {
return valueToTest
}
}