kopia lustrzana https://dev.funkwhale.audio/funkwhale/funkwhale
fix(front): translations
rodzic
02daeab46e
commit
60f38a3117
|
@ -1,105 +0,0 @@
|
|||
<script setup lang="ts">
|
||||
import { useIntervalFn, useStyleTag, useToggle, useWindowSize } from '@vueuse/core'
|
||||
import { computed, defineAsyncComponent, nextTick, onMounted } from 'vue'
|
||||
|
||||
import { useQueue } from '~/composables/audio/queue'
|
||||
import { useStore } from '~/store'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import onKeyboardShortcut from '~/composables/onKeyboardShortcut'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const ChannelUploadModal = defineAsyncComponent(() => import('~/components/channels/UploadModal.vue'))
|
||||
const PlaylistModal = defineAsyncComponent(() => import('~/components/playlists/PlaylistModal.vue'))
|
||||
const FilterModal = defineAsyncComponent(() => import('~/components/moderation/FilterModal.vue'))
|
||||
const ReportModal = defineAsyncComponent(() => import('~/components/moderation/ReportModal.vue'))
|
||||
const ServiceMessages = defineAsyncComponent(() => import('~/components/ServiceMessages.vue'))
|
||||
const ShortcutsModal = defineAsyncComponent(() => import('~/components/ShortcutsModal.vue'))
|
||||
const AudioPlayer = defineAsyncComponent(() => import('~/components/audio/Player.vue'))
|
||||
const Sidebar = defineAsyncComponent(() => import('~/components/Sidebar.vue'))
|
||||
const Queue = defineAsyncComponent(() => import('~/components/Queue.vue'))
|
||||
|
||||
const store = useStore()
|
||||
|
||||
// Tracks
|
||||
const { tracks } = useQueue()
|
||||
|
||||
// Fake content
|
||||
onMounted(async () => {
|
||||
await nextTick()
|
||||
document.getElementById('fake-content')?.classList.add('loaded')
|
||||
})
|
||||
|
||||
// Styles
|
||||
const customStylesheets = computed(() => {
|
||||
return store.state.instance.frontSettings.additionalStylesheets ?? []
|
||||
})
|
||||
|
||||
useStyleTag(computed(() => store.state.instance.settings.ui.custom_css.value))
|
||||
|
||||
// Time ago
|
||||
useIntervalFn(() => {
|
||||
// used to redraw ago dates every minute
|
||||
store.commit('ui/computeLastDate')
|
||||
}, 1000 * 60)
|
||||
|
||||
// Shortcuts
|
||||
const [showShortcutsModal, toggleShortcutsModal] = useToggle(false)
|
||||
onKeyboardShortcut('h', () => toggleShortcutsModal())
|
||||
|
||||
const { width } = useWindowSize()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
:key="store.state.instance.instanceUrl"
|
||||
:class="{
|
||||
'has-bottom-player': tracks.length > 0,
|
||||
'queue-focused': store.state.ui.queueFocused
|
||||
}"
|
||||
>
|
||||
<!-- here, we display custom stylesheets, if any -->
|
||||
<link
|
||||
v-for="url in customStylesheets"
|
||||
:key="url"
|
||||
rel="stylesheet"
|
||||
property="stylesheet"
|
||||
:href="url"
|
||||
>
|
||||
|
||||
<sidebar
|
||||
:width="width"
|
||||
@show:shortcuts-modal="toggleShortcutsModal"
|
||||
/>
|
||||
<service-messages />
|
||||
<transition name="queue">
|
||||
<queue v-show="store.state.ui.queueFocused" />
|
||||
</transition>
|
||||
|
||||
<router-view v-slot="{ Component }">
|
||||
<template v-if="Component">
|
||||
<keep-alive :max="1">
|
||||
<Suspense>
|
||||
<component :is="Component" />
|
||||
<template #fallback>
|
||||
<!-- TODO (wvffle): Add loader -->
|
||||
{{ t('App.loading') }}
|
||||
</template>
|
||||
</Suspense>
|
||||
</keep-alive>
|
||||
</template>
|
||||
<template v-else>
|
||||
<!-- Display a proper 404 page or error message -->
|
||||
<h1>404 - Page Not Found</h1>
|
||||
</template>
|
||||
</router-view>
|
||||
|
||||
<audio-player />
|
||||
<playlist-modal v-if="store.state.auth.authenticated" />
|
||||
<channel-upload-modal v-if="store.state.auth.authenticated" />
|
||||
<filter-modal v-if="store.state.auth.authenticated" />
|
||||
<report-modal />
|
||||
<shortcuts-modal v-model:show="showShortcutsModal" />
|
||||
</div>
|
||||
</template>
|
|
@ -7,6 +7,8 @@ import { ref, computed, watch, nextTick } from 'vue'
|
|||
import { useStore } from '~/store'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
// TODO: Delete this file?
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
interface Props {
|
||||
|
@ -65,6 +67,7 @@ const checkAndSwitch = async (url: string) => {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<!-- eslint-disable @intlify/vue-i18n/no-raw-text -->
|
||||
<Modal
|
||||
v-model="show"
|
||||
:title="t('views.ChooseInstance.header.chooseInstance')"
|
||||
|
@ -181,4 +184,5 @@ const checkAndSwitch = async (url: string) => {
|
|||
</button>
|
||||
</div>
|
||||
</Modal>
|
||||
<!-- eslint-disable @intlify/vue-i18n/no-raw-text -->
|
||||
</template>
|
||||
|
|
|
@ -250,8 +250,7 @@ const save = async () => {
|
|||
red
|
||||
>
|
||||
<h4 class="header">
|
||||
{{ group.label }}:
|
||||
{{ t('components.admin.SettingsGroup.header.error') }}
|
||||
{{ t('components.admin.SettingsGroup.header.error', {label: group.label}) }}
|
||||
</h4>
|
||||
<ul class="list">
|
||||
<li
|
||||
|
|
|
@ -71,7 +71,7 @@ watch(albums, (value) => {
|
|||
icon="bi-plus"
|
||||
:to="useModal('album').to"
|
||||
>
|
||||
Add Album
|
||||
{{ t('components.channels.AlbumSelect.add') }}
|
||||
<AlbumModal
|
||||
v-model="model.channel"
|
||||
@created="fetchAlbums"
|
||||
|
|
|
@ -6,6 +6,7 @@ import { computed, reactive, ref } from 'vue'
|
|||
import { isEqual, clone } from 'lodash-es'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useStore } from '~/store'
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
import axios from 'axios'
|
||||
|
||||
|
@ -36,6 +37,7 @@ const props = withDefaults(defineProps<Props>(), {
|
|||
const { t } = useI18n()
|
||||
const configs = useEditConfigs()
|
||||
const store = useStore()
|
||||
const route = useRoute()
|
||||
|
||||
const config = computed(() => configs[props.objectType])
|
||||
const currentState = computed(() => config.value.fields.reduce((state: ReviewState, field) => {
|
||||
|
@ -157,13 +159,15 @@ const resetField = (fieldId: string) => {
|
|||
{{ t('components.library.EditForm.button.new') }}
|
||||
</Button>
|
||||
|
||||
<!-- TODO: Implement link back to all types of object -->
|
||||
<Link
|
||||
v-if="route.path.includes('album')"
|
||||
solid
|
||||
secondary
|
||||
raised
|
||||
:to="{ name: 'library.albums.detail', params: { id: object.id } }"
|
||||
>
|
||||
Back to Album
|
||||
{{ t('components.library.EditForm.button.backToAlbum') }}
|
||||
</Link>
|
||||
</Alert>
|
||||
<Layout
|
||||
|
|
|
@ -426,7 +426,7 @@ const isServerDisclosureOpen = ref(false)
|
|||
'yellow': files.length > uploadedFilesCount + erroredFilesCount
|
||||
}"
|
||||
>
|
||||
{{ uploadedFilesCount + erroredFilesCount }} / {{ files.length }}
|
||||
{{ t('components.library.FileUpload.table.upload.progressNum', {current: uploadedFilesCount + erroredFilesCount, total: files.length}) }}
|
||||
</Pill>
|
||||
</Layout>
|
||||
<Layout
|
||||
|
@ -435,7 +435,7 @@ const isServerDisclosureOpen = ref(false)
|
|||
>
|
||||
<label>{{ t('components.library.FileUpload.link.processing') }}</label>
|
||||
<Pill>
|
||||
{{ processedFilesCount }} / {{ processableFiles }}
|
||||
{{ t('components.library.FileUpload.table.upload.progressNum', {current: processedFilesCount, total: processableFiles}) }}
|
||||
</Pill>
|
||||
</Layout>
|
||||
</Layout>
|
||||
|
|
|
@ -330,7 +330,7 @@
|
|||
"save": "Save"
|
||||
},
|
||||
"header": {
|
||||
"error": "Error while saving settings.",
|
||||
"error": "{label}: Error while saving settings.",
|
||||
"image": "Current image"
|
||||
},
|
||||
"message": {
|
||||
|
@ -1027,6 +1027,7 @@
|
|||
}
|
||||
},
|
||||
"AlbumSelect": {
|
||||
"add": "Add Album",
|
||||
"label": {
|
||||
"album": "Album",
|
||||
"series": "Series"
|
||||
|
@ -1642,6 +1643,7 @@
|
|||
},
|
||||
"EditForm": {
|
||||
"button": {
|
||||
"backToAlbum": "Back to Album",
|
||||
"cancel": "Cancel",
|
||||
"clear": "Clear",
|
||||
"new": "Submit another edit",
|
||||
|
@ -1716,6 +1718,7 @@
|
|||
"size": "Size",
|
||||
"status": "Status"
|
||||
},
|
||||
"progressNum": "{current} / {total}",
|
||||
"progress": "{percent}%",
|
||||
"status": {
|
||||
"pending": "Pending",
|
||||
|
@ -3253,6 +3256,16 @@
|
|||
"newAppVersion": "A new version of the app is available."
|
||||
}
|
||||
},
|
||||
"modals": {
|
||||
"search": {
|
||||
"tryAgain": "If the following link does not work, wait a few seconds and try again"
|
||||
},
|
||||
"upload": {
|
||||
"library": "Host music you listen to",
|
||||
"musicChannel": "Publish music you make",
|
||||
"podcastChannel": "Publish podcasts you make"
|
||||
}
|
||||
},
|
||||
"views": {
|
||||
"ChooseInstance": {
|
||||
"button": {
|
||||
|
@ -4371,7 +4384,7 @@
|
|||
"currentUsage": "Current usage"
|
||||
},
|
||||
"label": {
|
||||
"currentUsage": "{amount} used on {max} allowed",
|
||||
"currentUsage": "{currentAmount} used on {max} allowed",
|
||||
"errored": "Errored files",
|
||||
"pending": "Pending files",
|
||||
"percentUsed": "{progress}%",
|
||||
|
@ -4583,7 +4596,9 @@
|
|||
"tracks": "Tracks"
|
||||
},
|
||||
"meta": {
|
||||
"tracks": "Playlist containing {n} track, by {username} | Playlist containing {n} tracks, by {username}"
|
||||
"attribution": "by",
|
||||
"tracks": "Playlist containing {n} track, by {username} | Playlist containing {n} tracks, by {username}",
|
||||
"updated": "updated"
|
||||
},
|
||||
"modal": {
|
||||
"delete": {
|
||||
|
|
|
@ -355,19 +355,6 @@ const moderationNotifications = computed(() =>
|
|||
{{ t('components.Sidebar.link.about') }}
|
||||
</Link>
|
||||
<Spacer shrink />
|
||||
<Link
|
||||
thin-font
|
||||
to="/privacy"
|
||||
>
|
||||
Privacy
|
||||
</Link>
|
||||
<Spacer shrink />
|
||||
<Link
|
||||
thin-font
|
||||
to="/legal"
|
||||
>
|
||||
Legal
|
||||
</Link>
|
||||
</Layout>
|
||||
</Layout>
|
||||
</Layout>
|
||||
|
|
|
@ -6,6 +6,8 @@ import UploadList from '~/ui/components/UploadList.vue'
|
|||
import { UseTimeAgo } from '@vueuse/components'
|
||||
import { Icon } from '@iconify/vue'
|
||||
|
||||
// TODO: Delete this file, please.
|
||||
|
||||
defineProps<{ groups: UploadGroup[], isUploading?: boolean }>()
|
||||
|
||||
const openUploadGroup = ref<UploadGroup>()
|
||||
|
@ -45,6 +47,7 @@ const getDescription = (group: UploadGroup) => {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<!-- eslint-disable @intlify/vue-i18n/no-raw-text -->
|
||||
<div>
|
||||
<div
|
||||
v-for="group of groups"
|
||||
|
@ -161,6 +164,7 @@ const getDescription = (group: UploadGroup) => {
|
|||
</VerticalCollapse>
|
||||
</div>
|
||||
</div>
|
||||
<!-- eslint-enable @intlify/vue-i18n/no-raw-text -->
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
|
|
@ -10,9 +10,12 @@ defineProps<{
|
|||
wide?: boolean
|
||||
}>()
|
||||
|
||||
// TODO: Delete this file, please.
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- eslint-disable @intlify/vue-i18n/no-raw-text -->
|
||||
<div class="file-list">
|
||||
<div
|
||||
v-for="track in uploads"
|
||||
|
@ -106,6 +109,7 @@ defineProps<{
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
<!-- eslint-enable @intlify/vue-i18n/no-raw-text -->
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
|
|
@ -63,7 +63,7 @@ const continueInBackground = () => {
|
|||
return router.push('/upload/running')
|
||||
}
|
||||
|
||||
// TODO (whole file): Translations
|
||||
// TODO (whole file): Delete this file, please.
|
||||
|
||||
// Sorting
|
||||
const sortItems = reactive([
|
||||
|
@ -94,6 +94,7 @@ const isOpen = computed({
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<!-- eslint-disable @intlify/vue-i18n/no-raw-text -->
|
||||
<Modal
|
||||
v-model="isOpen"
|
||||
title="Upload..."
|
||||
|
@ -162,6 +163,7 @@ const isOpen = computed({
|
|||
</Button>
|
||||
</template>
|
||||
</Modal>
|
||||
<!-- eslint-enable @intlify/vue-i18n/no-raw-text -->
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
|
|
@ -492,7 +492,7 @@ watch(queryDebounced, search, { immediate: true })
|
|||
<!-- If response has "url": "webfinger://node1@node1.funkwhale.test" -> Link to go directly to the federation page -->
|
||||
|
||||
<span v-if="category.type === 'rss' && count(category) > 0">
|
||||
<Alert>If the following link does not work, wait a few seconds and try again</Alert>
|
||||
<Alert>{{ t('modals.search.tryAgain') }}</Alert>
|
||||
<Link
|
||||
v-for="channel in resultsPerCategory(category)"
|
||||
:key="channel.artist.fid"
|
||||
|
@ -504,7 +504,8 @@ watch(queryDebounced, search, { immediate: true })
|
|||
</span>
|
||||
|
||||
<span v-else-if="category.type === 'federation'">
|
||||
TODO: {{ resultsPerCategory(category) }}
|
||||
<!-- TODO: Federation search: backend adapter + display, fix results_per_category query -->
|
||||
<!-- {{ resultsPerCategory(category) }} -->
|
||||
</span>
|
||||
|
||||
<EmptyState
|
||||
|
|
|
@ -110,7 +110,7 @@ const channelUpload = ref()
|
|||
:class="$style.icon"
|
||||
/>
|
||||
</template>
|
||||
{{ "Host music you listen to" /* TODO: Translate */ }}
|
||||
{{ t('modals.upload.library') }}
|
||||
</Card>
|
||||
<Card
|
||||
small
|
||||
|
@ -125,7 +125,7 @@ const channelUpload = ref()
|
|||
:class="$style.icon"
|
||||
/>
|
||||
</template>
|
||||
{{ "Publish music you make" /* TODO: Translate */ }}
|
||||
{{ t('modals.upload.musicChannel') }}
|
||||
</Card>
|
||||
<Card
|
||||
small
|
||||
|
@ -140,7 +140,7 @@ const channelUpload = ref()
|
|||
:class="$style.icon"
|
||||
/>
|
||||
</template>
|
||||
{{ "Publish podcasts you make" /* TODO: Translate */ }}
|
||||
{{ t('modals.upload.podcastChannel') }}
|
||||
</Card>
|
||||
</Layout>
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@ import { useUploadsStore } from '~/ui/stores/upload'
|
|||
import { bytesToHumanSize } from '~/ui/composables/bytes'
|
||||
import UploadModal from '~/ui/components/UploadModal.vue'
|
||||
|
||||
// TODO: Delete this file?
|
||||
|
||||
const filesystemStats = reactive({
|
||||
total: 10737418240,
|
||||
used: 3e9
|
||||
|
@ -40,6 +42,7 @@ const tabs = computed(() => [
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<!-- eslint-disable @intlify/vue-i18n/no-raw-text -->
|
||||
<div class="flex items-center">
|
||||
<h1 class="mr-auto">
|
||||
Upload
|
||||
|
@ -82,6 +85,7 @@ const tabs = computed(() => [
|
|||
<RouterView />
|
||||
|
||||
<UploadModal />
|
||||
<!-- eslint-enable @intlify/vue-i18n/no-raw-text -->
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
|
|
@ -5,6 +5,8 @@ import { bytesToHumanSize } from '~/ui/composables/bytes'
|
|||
import { useUploadsStore, type UploadGroupEntry } from '~/ui/stores/upload'
|
||||
import CoverArt from '~/ui/components/CoverArt.vue'
|
||||
|
||||
// TODO: Delete this file?
|
||||
|
||||
interface Recording {
|
||||
guid: string
|
||||
title: string
|
||||
|
@ -49,6 +51,7 @@ const columns = [
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<!-- eslint-disable @intlify/vue-i18n/no-raw-text -->
|
||||
<div
|
||||
v-if="allTracks.length === 0"
|
||||
class="flex flex-col items-center py-32"
|
||||
|
@ -80,6 +83,7 @@ const columns = [
|
|||
{{ intl.format(value) }}
|
||||
</template>
|
||||
</FwTable>
|
||||
<!-- eslint-enable @intlify/vue-i18n/no-raw-text -->
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
|
|
@ -5,6 +5,8 @@ import { ref } from 'vue'
|
|||
import axios from 'axios'
|
||||
import { useAsyncState } from '@vueuse/core'
|
||||
|
||||
// TODO: Delete this file?
|
||||
|
||||
interface Tab {
|
||||
label: string
|
||||
icon: string
|
||||
|
@ -49,6 +51,7 @@ const { state: items } = useAsyncState(
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<!-- eslint-disable @intlify/vue-i18n/no-raw-text -->
|
||||
<div class="upload">
|
||||
<p> Select a destination for your audio files: </p>
|
||||
|
||||
|
@ -98,6 +101,7 @@ const { state: items } = useAsyncState(
|
|||
Open library
|
||||
</FwButton>
|
||||
</div>
|
||||
<!-- eslint-enable @intlify/vue-i18n/no-raw-text -->
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
|
|
@ -22,6 +22,8 @@ import Button from '~/components/ui/Button.vue'
|
|||
import useErrorHandler from '~/composables/useErrorHandler'
|
||||
import useLogger from '~/composables/useLogger'
|
||||
|
||||
// TODO: Depreciate & refactor essential functionality to new ui/modals/Search.vue
|
||||
|
||||
type QueryType = 'artists' | 'albums' | 'tracks' | 'playlists' | 'tags' | 'radios' | 'podcasts' | 'series' | 'rss'
|
||||
|
||||
const type = useRouteQuery<QueryType>('type', 'artists')
|
||||
|
@ -226,7 +228,6 @@ const radioConfig = computed(() => {
|
|||
class="main"
|
||||
>
|
||||
<section class="ui vertical stripe segment">
|
||||
/front/src/components/audio/Search.vue
|
||||
<div
|
||||
v-if="id"
|
||||
class="ui small text container"
|
||||
|
|
|
@ -84,7 +84,7 @@ const purgeErroredFiles = () => purge('errored')
|
|||
v-if="quotaStatus"
|
||||
class="label"
|
||||
>
|
||||
{{ t('views.content.libraries.Quota.label.currentUsage', {max: humanSize(quotaStatus.max * 1000 * 1000), current: humanSize(quotaStatus.current * 1000 * 1000)}) }}
|
||||
{{ t('views.content.libraries.Quota.label.currentUsage', {max: humanSize(quotaStatus.max * 1000 * 1000), currentAmount: humanSize(quotaStatus.current * 1000 * 1000)}) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui hidden divider" />
|
||||
|
|
|
@ -21,6 +21,8 @@ import Upload from '~/ui/pages/upload.vue'
|
|||
|
||||
import useErrorHandler from '~/composables/useErrorHandler'
|
||||
|
||||
// TODO: Delete this file.
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const router = useRouter()
|
||||
|
@ -103,6 +105,7 @@ const openModal = (object_: Library | Channel) => {
|
|||
|
||||
<template>
|
||||
<!-- TODO: Remove this module -->
|
||||
<!-- eslint-disable @intlify/vue-i18n/no-raw-text -->
|
||||
<section
|
||||
v-title="labels.title"
|
||||
class="ui vertical aligned stripe segment"
|
||||
|
@ -160,4 +163,5 @@ const openModal = (object_: Library | Channel) => {
|
|||
<upload />
|
||||
</fw-modal>
|
||||
<!-- <channel-upload-modal v-if="store.state.auth.authenticated" /> -->
|
||||
<!-- eslint-enable @intlify/vue-i18n/no-raw-text -->
|
||||
</template>
|
||||
|
|
|
@ -162,15 +162,14 @@ const deletePlaylist = async () => {
|
|||
flex
|
||||
gap-8
|
||||
>
|
||||
<!-- TODO: Translations -->
|
||||
by
|
||||
{{ t('views.playlists.Detail.meta.attribution') }}
|
||||
<ActorLink
|
||||
:actor="playlist.actor"
|
||||
:avatar="false"
|
||||
:discrete="true"
|
||||
/>
|
||||
<i class="bi bi-dot" />
|
||||
updated
|
||||
{{ t('views.playlists.Detail.meta.updated') }}
|
||||
<HumanDate
|
||||
:date="playlist.modification_date"
|
||||
/>
|
||||
|
|
Ładowanie…
Reference in New Issue