Start to clean up structure

This commit is contained in:
Ciarán Ainsworth 2022-09-18 23:12:39 +00:00 committed by Kasper Seweryn
parent 58df446539
commit 9e34fbc47e
23 changed files with 772 additions and 582 deletions

View File

@ -67,10 +67,10 @@ const headerStyle = computed(() => {
<div class="column" /> <div class="column" />
</div> </div>
<h2 class="header"> <h2 class="header">
{{ $t('components.About.funkwhaleHeader') }} {{ $t('components.About.header.funkwhale') }}
</h2> </h2>
<p> <p>
{{ $t('components.About.funkwhaleDescription') }} {{ $t('components.About.description.funkwhale') }}
</p> </p>
</div> </div>
</div> </div>
@ -84,14 +84,14 @@ const headerStyle = computed(() => {
class="signup-form content" class="signup-form content"
> >
<h3 class="header"> <h3 class="header">
{{ $t('components.About.signupHeader') }} {{ $t('components.About.header.signup') }}
</h3> </h3>
<template v-if="openRegistrations"> <template v-if="openRegistrations">
<p> <p>
{{ $t('components.About.signupDescription') }} {{ $t('components.About.description.signup') }}
</p> </p>
<p v-if="defaultUploadQuota"> <p v-if="defaultUploadQuota">
{{ $t('components.About.quotaDescription', {quota: defaultUploadQuota}) }} {{ $t('components.About.description.quota', {quota: defaultUploadQuota}) }}
</p> </p>
<signup-form <signup-form
button-classes="success" button-classes="success"
@ -100,7 +100,7 @@ const headerStyle = computed(() => {
</template> </template>
<div v-else> <div v-else>
<p> <p>
{{ $t('components.About.registrationsClosedHelp') }} {{ $t('components.About.help.closedRegistrations') }}
</p> </p>
<a <a
@ -108,7 +108,7 @@ const headerStyle = computed(() => {
rel="noopener" rel="noopener"
href="https://funkwhale.audio/#get-started" href="https://funkwhale.audio/#get-started"
> >
{{ $t('components.About.findOtherPod') }} {{ $t('components.About.link.findOtherPod') }}
&nbsp;<i class="external alternate icon" /> &nbsp;<i class="external alternate icon" />
</a> </a>
</div> </div>
@ -118,13 +118,13 @@ const headerStyle = computed(() => {
class="signup-form content" class="signup-form content"
> >
<h3 class="header"> <h3 class="header">
{{ $t('components.About.signupHeader') }} {{ $t('components.About.header.signup') }}
<div class="ui positive message"> <div class="ui positive message">
<div class="header"> <div class="header">
{{ $t('components.About.alreadyLoggedIn') }} {{ $t('components.About.message.loggedIn') }}
</div> </div>
<p> <p>
{{ $t('components.About.greetingMessage', {username: $store.state.auth.username}) }} {{ $t('components.About.message.greeting', {username: $store.state.auth.username}) }}
</p> </p>
</div> </div>
</h3> </h3>
@ -145,7 +145,7 @@ const headerStyle = computed(() => {
id="description" id="description"
class="ui header" class="ui header"
> >
{{ $t('components.About.aboutPodHeader') }} {{ $t('components.About.header.aboutPod') }}
</h3> </h3>
<div <div
v-if="shortDescription" v-if="shortDescription"
@ -154,7 +154,7 @@ const headerStyle = computed(() => {
{{ shortDescription }} {{ shortDescription }}
</div> </div>
<p v-else> <p v-else>
{{ $t('components.About.noDescription') }} {{ $t('components.About.placeholder.noDescription') }}
</p> </p>
<template v-if="stats"> <template v-if="stats">
@ -164,14 +164,14 @@ const headerStyle = computed(() => {
<span class="statistics-figure ui text"> <span class="statistics-figure ui text">
<span class="ui big text"><strong>{{ stats.users.toLocaleString($store.state.ui.momentLocale) }}</strong></span> <span class="ui big text"><strong>{{ stats.users.toLocaleString($store.state.ui.momentLocale) }}</strong></span>
<br> <br>
{{ $t('components.About.activeUsers', {users: stats.users}) }} {{ $t('components.About.stat.activeUsers', {users: stats.users}) }}
</span> </span>
</div> </div>
<div class="column"> <div class="column">
<span class="statistics-figure ui text"> <span class="statistics-figure ui text">
<span class="ui big text"><strong>{{ stats.hours.toLocaleString($store.state.ui.momentLocale) }}</strong></span> <span class="ui big text"><strong>{{ stats.hours.toLocaleString($store.state.ui.momentLocale) }}</strong></span>
<br> <br>
{{ $t('components.About.hoursOfMusic', {hours: stats.hours}) }} {{ $t('components.About.stat.hoursOfMusic', {hours: stats.hours}) }}
</span> </span>
</div> </div>
</div> </div>
@ -182,7 +182,7 @@ const headerStyle = computed(() => {
to="/about/pod" to="/about/pod"
class="ui fluid basic secondary button" class="ui fluid basic secondary button"
> >
{{ $t('components.About.learnMoreLink') }} {{ $t('components.About.link.learnMore') }}
</router-link> </router-link>
</div> </div>
</div> </div>
@ -201,10 +201,10 @@ const headerStyle = computed(() => {
id="description" id="description"
class="ui header" class="ui header"
> >
{{ $t('components.About.publicContentHeader') }} {{ $t('components.About.header.publicContent') }}
</h3> </h3>
<p> <p>
{{ $t('components.About.publicContentDescription') }} {{ $t('components.About.description.publicContent') }}
</p> </p>
</div> </div>
</router-link> </router-link>
@ -218,11 +218,11 @@ const headerStyle = computed(() => {
id="description" id="description"
class="ui header" class="ui header"
> >
{{ $t('components.About.findOtherPod') }} {{ $t('components.About.link.findOtherPod') }}
&nbsp;<i class="external alternate icon" /> &nbsp;<i class="external alternate icon" />
</h3> </h3>
<p> <p>
{{ $t('components.About.publicContentDescription') }} {{ $t('components.About.description.publicContent') }}
</p> </p>
</div> </div>
</a> </a>
@ -236,11 +236,11 @@ const headerStyle = computed(() => {
id="description" id="description"
class="ui header" class="ui header"
> >
{{ $t('components.About.findAppHeader') }} {{ $t('components.About.header.findApp') }}
&nbsp;<i class="external alternate icon" /> &nbsp;<i class="external alternate icon" />
</h3> </h3>
<p> <p>
{{ $t('components.About.findAppDescription') }} {{ $t('components.About.description.findApp') }}
</p> </p>
</div> </div>
</a> </a>
@ -250,7 +250,7 @@ const headerStyle = computed(() => {
to="/about/pod" to="/about/pod"
class="ui right floated basic secondary button" class="ui right floated basic secondary button"
> >
{{ $t('components.About.aboutPodHeader') }} {{ $t('components.About.header.aboutPod') }}
<i class="icon arrow right" /> <i class="icon arrow right" />
</router-link> </router-link>
</div> </div>

View File

@ -99,32 +99,32 @@ const headerStyle = computed(() => {
to="/about/pod" to="/about/pod"
class="item" class="item"
> >
{{ $t('components.AboutPod.aboutPod') }} {{ $t('components.AboutPod.link.about') }}
</router-link> </router-link>
<router-link <router-link
to="/about/pod#rules" to="/about/pod#rules"
class="item" class="item"
> >
{{ $t('components.AboutPod.rules') }} {{ $t('components.AboutPod.link.rules') }}
</router-link> </router-link>
<router-link <router-link
to="/about/pod#terms" to="/about/pod#terms"
class="item" class="item"
> >
{{ $t('components.AboutPod.termsAndPrivacy') }} {{ $t('components.AboutPod.link.terms') }}
</router-link> </router-link>
<router-link <router-link
to="/about/pod#features" to="/about/pod#features"
class="item" class="item"
> >
{{ $t('components.AboutPod.features') }} {{ $t('components.AboutPod.link.features') }}
</router-link> </router-link>
<router-link <router-link
v-if="stats" v-if="stats"
to="/about/pod#statistics" to="/about/pod#statistics"
class="item" class="item"
> >
{{ $t('components.AboutPod.statistics') }} {{ $t('components.AboutPod.link.statistics') }}
</router-link> </router-link>
</div> </div>
</div> </div>
@ -134,49 +134,49 @@ const headerStyle = computed(() => {
id="description about-this-pod" id="description about-this-pod"
class="ui header" class="ui header"
> >
{{ $t('components.AboutPod.aboutPod') }} {{ $t('components.AboutPod.header.about') }}
</h2> </h2>
<sanitized-html <sanitized-html
v-if="longDescription" v-if="longDescription"
:html="longDescription" :html="longDescription"
/> />
<p v-else> <p v-else>
{{ $t('components.AboutPod.noDescription') }} {{ $t('components.AboutPod.placeholder.noDescription') }}
</p> </p>
<h3 <h3
id="rules" id="rules"
class="ui header" class="ui header"
> >
{{ $t('components.AboutPod.rules') }} {{ $t('components.AboutPod.header.rules') }}
</h3> </h3>
<sanitized-html <sanitized-html
v-if="rules" v-if="rules"
:html="rules" :html="rules"
/> />
<p v-else> <p v-else>
{{ $t('components.AboutPod.noRules') }} {{ $t('components.AboutPod.placeholder.noRules') }}
</p> </p>
<h3 <h3
id="terms" id="terms"
class="ui header" class="ui header"
> >
{{ $t('components.AboutPod.termsAndPrivacy') }} {{ $t('components.AboutPod.header.terms') }}
</h3> </h3>
<sanitized-html <sanitized-html
v-if="terms" v-if="terms"
:html="terms" :html="terms"
/> />
<p v-else> <p v-else>
{{ $t('components.AboutPod.noTerms') }} {{ $t('components.AboutPod.placeholder.noTerms') }}
</p> </p>
<h3 <h3
id="features" id="features"
class="header" class="header"
> >
{{ $t('components.AboutPod.features') }} {{ $t('components.AboutPod.header.features') }}
</h3> </h3>
<div class="features-container ui two column stackable grid"> <div class="features-container ui two column stackable grid">
<div class="column"> <div class="column">
@ -184,7 +184,7 @@ const headerStyle = computed(() => {
<tbody> <tbody>
<tr> <tr>
<td> <td>
{{ $t('components.AboutPod.funkwhaleVersion') }} {{ $t('components.AboutPod.feature.version') }}
</td> </td>
<td <td
v-if="version" v-if="version"
@ -205,7 +205,7 @@ const headerStyle = computed(() => {
</tr> </tr>
<tr> <tr>
<td> <td>
{{ $t('components.AboutPod.federation') }} {{ $t('components.AboutPod.feature.federation') }}
</td> </td>
<td <td
v-if="federationEnabled" v-if="federationEnabled"
@ -213,7 +213,7 @@ const headerStyle = computed(() => {
> >
<span class="features-status ui text"> <span class="features-status ui text">
<i class="check icon" /> <i class="check icon" />
{{ $t('components.AboutPod.enabled') }} {{ $t('components.AboutPod.feature.status.enabled') }}
</span> </span>
</td> </td>
<td <td
@ -222,13 +222,13 @@ const headerStyle = computed(() => {
> >
<span class="features-status ui text"> <span class="features-status ui text">
<i class="x icon" /> <i class="x icon" />
{{ $t('components.AboutPod.disabled') }} {{ $t('components.AboutPod.feature.status.disabled') }}
</span> </span>
</td> </td>
</tr> </tr>
<tr> <tr>
<td> <td>
{{ $t('components.AboutPod.allowList') }} {{ $t('components.AboutPod.feature.allowList') }}
</td> </td>
<td <td
v-if="allowListEnabled" v-if="allowListEnabled"
@ -236,7 +236,7 @@ const headerStyle = computed(() => {
> >
<span class="features-status ui text"> <span class="features-status ui text">
<i class="check icon" /> <i class="check icon" />
{{ $t('components.AboutPod.enabled') }} {{ $t('components.AboutPod.feature.status.enabled') }}
</span> </span>
</td> </td>
<td <td
@ -245,7 +245,7 @@ const headerStyle = computed(() => {
> >
<span class="features-status ui text"> <span class="features-status ui text">
<i class="x icon" /> <i class="x icon" />
{{ $t('components.AboutPod.disabled') }} {{ $t('components.AboutPod.feature.status.disabled') }}
</span> </span>
</td> </td>
</tr> </tr>
@ -257,7 +257,7 @@ const headerStyle = computed(() => {
<tbody> <tbody>
<tr> <tr>
<td> <td>
{{ $t('components.AboutPod.anonymousAccess') }} {{ $t('components.AboutPod.feature.anonymousAccess') }}
</td> </td>
<td <td
v-if="anonymousCanListen" v-if="anonymousCanListen"
@ -265,7 +265,7 @@ const headerStyle = computed(() => {
> >
<span class="features-status ui text"> <span class="features-status ui text">
<i class="check icon" /> <i class="check icon" />
{{ $t('components.AboutPod.enabled') }} {{ $t('components.AboutPod.feature.status.enabled') }}
</span> </span>
</td> </td>
<td <td
@ -274,13 +274,13 @@ const headerStyle = computed(() => {
> >
<span class="features-status ui text"> <span class="features-status ui text">
<i class="x icon" /> <i class="x icon" />
{{ $t('components.AboutPod.disabled') }} {{ $t('components.AboutPod.feature.status.disabled') }}
</span> </span>
</td> </td>
</tr> </tr>
<tr> <tr>
<td> <td>
{{ $t('components.AboutPod.registrations') }} {{ $t('components.AboutPod.feature.registrations') }}
</td> </td>
<td <td
v-if="openRegistrations" v-if="openRegistrations"
@ -288,7 +288,7 @@ const headerStyle = computed(() => {
> >
<span class="features-status ui text"> <span class="features-status ui text">
<i class="check icon" /> <i class="check icon" />
{{ $t('components.AboutPod.open') }} {{ $t('components.AboutPod.feature.status.open') }}
</span> </span>
</td> </td>
<td <td
@ -297,13 +297,13 @@ const headerStyle = computed(() => {
> >
<span class="features-status ui text"> <span class="features-status ui text">
<i class="x icon" /> <i class="x icon" />
{{ $t('components.AboutPod.closed') }} {{ $t('components.AboutPod.feature.status.closed') }}
</span> </span>
</td> </td>
</tr> </tr>
<tr> <tr>
<td> <td>
{{ $t('components.AboutPod.uploadQuota') }} {{ $t('components.AboutPod.feature.quota') }}
</td> </td>
<td <td
v-if="defaultUploadQuota" v-if="defaultUploadQuota"
@ -332,7 +332,7 @@ const headerStyle = computed(() => {
id="statistics" id="statistics"
class="header" class="header"
> >
{{ $t('components.AboutPod.statistics') }} {{ $t('components.AboutPod.header.statistics') }}
</h3> </h3>
<div class="statistics-container"> <div class="statistics-container">
<div <div
@ -342,7 +342,7 @@ const headerStyle = computed(() => {
<span class="statistics-figure ui text"> <span class="statistics-figure ui text">
<span class="ui big text"><strong>{{ stats.hours.toLocaleString($store.state.ui.momentLocale) }}</strong></span> <span class="ui big text"><strong>{{ stats.hours.toLocaleString($store.state.ui.momentLocale) }}</strong></span>
<br> <br>
{{ $t('components.AboutPod.hoursOfMusic', {hours: stats.hours}) }} {{ $t('components.AboutPod.stat.hoursOfMusic', {hours: stats.hours}) }}
</span> </span>
</div> </div>
<div <div
@ -352,7 +352,7 @@ const headerStyle = computed(() => {
<span class="statistics-figure ui text"> <span class="statistics-figure ui text">
<span class="ui big text"><strong>{{ stats.artists.toLocaleString($store.state.ui.momentLocale) }}</strong></span> <span class="ui big text"><strong>{{ stats.artists.toLocaleString($store.state.ui.momentLocale) }}</strong></span>
<br> <br>
{{ $t('components.AboutPod.artistsCount', {artists: stats.artists}) }} {{ $t('components.AboutPod.stat.artistsCount', {artists: stats.artists}) }}
</span> </span>
</div> </div>
<div <div
@ -362,7 +362,7 @@ const headerStyle = computed(() => {
<span class="statistics-figure ui text"> <span class="statistics-figure ui text">
<span class="ui big text"><strong>{{ stats.albums.toLocaleString($store.state.ui.momentLocale) }}</strong></span> <span class="ui big text"><strong>{{ stats.albums.toLocaleString($store.state.ui.momentLocale) }}</strong></span>
<br> <br>
{{ $t('components.AboutPod.albumsCount', {albums: stats.albums}) }} {{ $t('components.AboutPod.stat.albumsCount', {albums: stats.albums}) }}
</span> </span>
</div> </div>
<div <div
@ -372,7 +372,7 @@ const headerStyle = computed(() => {
<span class="statistics-figure ui text"> <span class="statistics-figure ui text">
<span class="ui big text"><strong>{{ stats.tracks.toLocaleString($store.state.ui.momentLocale) }}</strong></span> <span class="ui big text"><strong>{{ stats.tracks.toLocaleString($store.state.ui.momentLocale) }}</strong></span>
<br> <br>
{{ $t('components.AboutPod.tracksCount', {tracks: stats.tracks}) }} {{ $t('components.AboutPod.stat.tracksCount', {tracks: stats.tracks}) }}
</span> </span>
</div> </div>
<div <div
@ -382,7 +382,7 @@ const headerStyle = computed(() => {
<span class="statistics-figure ui text"> <span class="statistics-figure ui text">
<span class="ui big text"><strong>{{ stats.users.toLocaleString($store.state.ui.momentLocale) }}</strong></span> <span class="ui big text"><strong>{{ stats.users.toLocaleString($store.state.ui.momentLocale) }}</strong></span>
<br> <br>
{{ $t('components.AboutPod.activeUsers', {users: stats.users}) }} {{ $t('components.AboutPod.stat.activeUsers', {users: stats.users}) }}
</span> </span>
</div> </div>
<div <div
@ -392,7 +392,7 @@ const headerStyle = computed(() => {
<span class="statistics-figure ui text"> <span class="statistics-figure ui text">
<span class="ui big text"><strong>{{ stats.listenings.toLocaleString($store.state.ui.momentLocale) }}</strong></span> <span class="ui big text"><strong>{{ stats.listenings.toLocaleString($store.state.ui.momentLocale) }}</strong></span>
<br> <br>
{{ $t('components.AboutPod.listeningsCount', {listenings: stats.listenings}) }} {{ $t('components.AboutPod.stat.listeningsCount', {listenings: stats.listenings}) }}
</span> </span>
</div> </div>
</div> </div>
@ -403,13 +403,13 @@ const headerStyle = computed(() => {
id="contact" id="contact"
class="ui header" class="ui header"
> >
{{ $t('components.AboutPod.contactHeader') }} {{ $t('components.AboutPod.header.contact') }}
</h3> </h3>
<a <a
v-if="contactEmail" v-if="contactEmail"
:href="`mailto:${contactEmail}`" :href="`mailto:${contactEmail}`"
> >
{{ $t('components.AboutPod.contactEmail', {contactEmail: contactEmail}) }} {{ $t('components.AboutPod.message.contact', {contactEmail: contactEmail}) }}
</a> </a>
</template> </template>
@ -420,7 +420,7 @@ const headerStyle = computed(() => {
class="ui left floated basic secondary button" class="ui left floated basic secondary button"
> >
<i class="icon arrow left" /> <i class="icon arrow left" />
{{ $t('components.AboutPod.introductionLink') }} {{ $t('components.AboutPod.link.introduction') }}
</router-link> </router-link>
</div> </div>
</div> </div>

View File

@ -71,7 +71,7 @@ whenever(() => store.state.auth.authenticated, () => {
<div class="segment-content"> <div class="segment-content">
<h1 class="ui center aligned large header"> <h1 class="ui center aligned large header">
<span> <span>
{{ $t('components.Home.welcomeMessage', {podName: podName}) }} {{ $t('components.Home.header.welcome', {podName: podName}) }}
</span> </span>
<div <div
v-if="shortDescription" v-if="shortDescription"
@ -86,7 +86,7 @@ whenever(() => store.state.auth.authenticated, () => {
<div class="ui stackable grid"> <div class="ui stackable grid">
<div class="ten wide column"> <div class="ten wide column">
<h2 class="header"> <h2 class="header">
{{ $t('components.Home.aboutPod') }} {{ $t('components.Home.header.about') }}
</h2> </h2>
<div <div
id="pod" id="pod"
@ -95,7 +95,7 @@ whenever(() => store.state.auth.authenticated, () => {
<div class="ui stackable grid"> <div class="ui stackable grid">
<div class="eight wide column"> <div class="eight wide column">
<p v-if="!longDescription"> <p v-if="!longDescription">
{{ $t('components.Home.noDescription') }} {{ $t('components.Home.placeholder.noDescription') }}
</p> </p>
<template v-if="longDescription || rules"> <template v-if="longDescription || rules">
<sanitized-html <sanitized-html
@ -118,7 +118,7 @@ whenever(() => store.state.auth.authenticated, () => {
class="ui link" class="ui link"
:to="{name: 'about'}" :to="{name: 'about'}"
> >
{{ $t('components.Home.learnMore') }} {{ $t('components.Home.link.learnMore') }}
</router-link> </router-link>
</div> </div>
</div> </div>
@ -133,7 +133,7 @@ whenever(() => store.state.auth.authenticated, () => {
class="ui link" class="ui link"
:to="{name: 'about', hash: '#rules'}" :to="{name: 'about', hash: '#rules'}"
> >
{{ $t('components.Home.serverRules') }} {{ $t('components.Home.link.rules') }}
</router-link> </router-link>
</div> </div>
</div> </div>
@ -143,20 +143,20 @@ whenever(() => store.state.auth.authenticated, () => {
<div class="eight wide column"> <div class="eight wide column">
<template v-if="stats"> <template v-if="stats">
<h3 class="sub header"> <h3 class="sub header">
{{ $t('components.Home.statistics') }} {{ $t('components.Home.header.statistics') }}
</h3> </h3>
<p> <p>
<i class="user icon" /> <i class="user icon" />
{{ $t('components.Home.activeUsers', {users: stats.users}) }} {{ $t('components.Home.stat.activeUsers', {users: stats.users}) }}
</p> </p>
<p> <p>
<i class="music icon" /> <i class="music icon" />
{{ $t('components.Home.hoursOfMusic', {hours: stats.hours}) }} {{ $t('components.Home.stat.hoursOfMusic', {hours: stats.hours}) }}
</p> </p>
</template> </template>
<template v-if="contactEmail"> <template v-if="contactEmail">
<h3 class="sub header"> <h3 class="sub header">
{{ $t('components.Home.contactHeader') }} {{ $t('components.Home.header.contact') }}
</h3> </h3>
<i class="at icon" /> <i class="at icon" />
<a :href="`mailto:${contactEmail}`">{{ contactEmail }}</a> <a :href="`mailto:${contactEmail}`">{{ contactEmail }}</a>
@ -179,13 +179,13 @@ whenever(() => store.state.auth.authenticated, () => {
<div class="ui stackable grid"> <div class="ui stackable grid">
<div class="four wide column"> <div class="four wide column">
<h3 class="header"> <h3 class="header">
{{ $t('components.Home.aboutFunkwhale') }} {{ $t('components.Home.header.aboutFunkwhale') }}
</h3> </h3>
<p> <p>
{{ $t('components.Home.funkwhaleDescription') }} {{ $t('components.Home.description.funkwhale.paragraph1') }}
</p> </p>
<p> <p>
{{ $t('components.Home.funkwhaleAddendum') }} {{ $t('components.Home.description.funkwhale.paragraph2') }}
</p> </p>
<a <a
target="_blank" target="_blank"
@ -193,12 +193,12 @@ whenever(() => store.state.auth.authenticated, () => {
href="https://funkwhale.audio" href="https://funkwhale.audio"
> >
<i class="external alternate icon" /> <i class="external alternate icon" />
{{ $t('components.Home.websiteLink') }} {{ $t('components.Home.link.funkwhale') }}
</a> </a>
</div> </div>
<div class="four wide column"> <div class="four wide column">
<h3 class="header"> <h3 class="header">
{{ $t('components.Home.loginHeader') }} {{ $t('components.Home.header.login') }}
</h3> </h3>
<login-form <login-form
button-classes="success" button-classes="success"
@ -208,14 +208,14 @@ whenever(() => store.state.auth.authenticated, () => {
</div> </div>
<div class="four wide column"> <div class="four wide column">
<h3 class="header"> <h3 class="header">
{{ $t('components.Home.signupHeader') }} {{ $t('components.Home.header.signup') }}
</h3> </h3>
<template v-if="openRegistrations"> <template v-if="openRegistrations">
<p> <p>
{{ $t('components.Home.signupDescription') }} {{ $t('components.Home.description.signup') }}
</p> </p>
<p v-if="defaultUploadQuota"> <p v-if="defaultUploadQuota">
{{ $t('components.Home.uploadQuota', { quota: humanSize(defaultUploadQuota * 1000 * 1000) }) }} {{ $t('components.Home.description.quota', { quota: humanSize(defaultUploadQuota * 1000 * 1000) }) }}
</p> </p>
<signup-form <signup-form
button-classes="success" button-classes="success"
@ -224,7 +224,7 @@ whenever(() => store.state.auth.authenticated, () => {
</template> </template>
<div v-else> <div v-else>
<p> <p>
{{ $t('components.Home.registrationsClosed') }} {{ $t('components.Home.help.registrationsClosed') }}
</p> </p>
<a <a
target="_blank" target="_blank"
@ -232,14 +232,14 @@ whenever(() => store.state.auth.authenticated, () => {
href="https://funkwhale.audio/#get-started" href="https://funkwhale.audio/#get-started"
> >
<i class="external alternate icon" /> <i class="external alternate icon" />
{{ $t('components.Home.findOtherPod') }} {{ $t('components.Home.link.findOtherPod') }}
</a> </a>
</div> </div>
</div> </div>
<div class="four wide column"> <div class="four wide column">
<h3 class="header"> <h3 class="header">
{{ $t('components.Home.usefulLinks') }} {{ $t('components.Home.header.links') }}
</h3> </h3>
<div class="ui relaxed list"> <div class="ui relaxed list">
<div class="item"> <div class="item">
@ -250,10 +250,10 @@ whenever(() => store.state.auth.authenticated, () => {
class="header" class="header"
to="/library" to="/library"
> >
{{ $t('components.Home.browsePublicContent') }} {{ $t('components.Home.link.publicContent.label') }}
</router-link> </router-link>
<div class="description"> <div class="description">
{{ $t('components.Home.publicContentDescription') }} {{ $t('components.Home.link.publicContent.description') }}
</div> </div>
</div> </div>
</div> </div>
@ -266,10 +266,10 @@ whenever(() => store.state.auth.authenticated, () => {
target="_blank" target="_blank"
rel="noopener" rel="noopener"
> >
{{ $t('components.Home.mobileApps') }} {{ $t('components.Home.link.mobileApps.label') }}
</a> </a>
<div class="description"> <div class="description">
{{ $t('components.Home.mobileAppsDescription') }} {{ $t('components.Home.link.mobileApps.description') }}
</div> </div>
</div> </div>
</div> </div>
@ -282,10 +282,10 @@ whenever(() => store.state.auth.authenticated, () => {
target="_blank" target="_blank"
rel="noopener" rel="noopener"
> >
{{ $t('components.Home.userGuides') }} {{ $t('components.Home.link.userGuides.label') }}
</a> </a>
<div class="description"> <div class="description">
{{ $t('components.Home.userGuidesDescription') }} {{ $t('components.Home.link.userGuides.description') }}
</div> </div>
</div> </div>
</div> </div>
@ -302,16 +302,16 @@ whenever(() => store.state.auth.authenticated, () => {
:limit="10" :limit="10"
> >
<template #title> <template #title>
{{ $t('components.Home.recentlyAddedLabel') }} {{ $t('components.Home.header.newAlbums') }}
</template> </template>
<router-link to="/library"> <router-link to="/library">
{{ $t('components.Home.viewMore') }} {{ $t('components.Home.link.viewMore') }}
<div class="ui hidden divider" /> <div class="ui hidden divider" />
</router-link> </router-link>
</album-widget> </album-widget>
<div class="ui hidden section divider" /> <div class="ui hidden section divider" />
<h3 class="ui header"> <h3 class="ui header">
{{ $t('components.Home.newChannelsLabel') }} {{ $t('components.Home.header.newChannels') }}
</h3> </h3>
<channels-widget <channels-widget
:show-modification-date="true" :show-modification-date="true"

View File

@ -20,11 +20,11 @@ const labels = computed(() => ({
<h1 class="ui huge header"> <h1 class="ui huge header">
<i class="warning icon" /> <i class="warning icon" />
<div class="content"> <div class="content">
{{ $t('components.PageNotFound.pageNotFound') }} {{ $t('components.PageNotFound.header.pageNotFound') }}
</div> </div>
</h1> </h1>
<p> <p>
{{ $t('components.PageNotFound.pageNotFoundMessage') }} {{ $t('components.PageNotFound.message.pageNotFound') }}
</p> </p>
<a :href="path">{{ path }}</a> <a :href="path">{{ path }}</a>
<div class="ui hidden divider" /> <div class="ui hidden divider" />
@ -32,7 +32,7 @@ const labels = computed(() => ({
class="ui icon labeled right button" class="ui icon labeled right button"
to="/" to="/"
> >
{{ $t('components.PageNotFound.homeLink') }} {{ $t('components.PageNotFound.link.home') }}
<i class="right arrow icon" /> <i class="right arrow icon" />
</router-link> </router-link>
</div> </div>

View File

@ -55,19 +55,19 @@ const scrollLock = useScrollLock(document.body)
const store = useStore() const store = useStore()
const labels = computed(() => ({ const labels = computed(() => ({
queue: t('components.Queue.queue'), queue: t('components.Queue.label.queue'),
populating: t('components.Queue.queue.populatingRadio'), populating: t('components.Queue.queue.label.populatingRadio'),
duration: t('components.Queue.duration'), duration: t('components.Queue.label.duration'),
addArtistContentFilter: t('components.Queue.addArtistContentFilter'), addArtistContentFilter: t('components.Queue.label.addArtistContentFilter'),
restart: t('components.Queue.restart'), restart: t('components.Queue.label.restart'),
previous: t('components.Queue.previous'), previous: t('components.Queue.label.previous'),
next: t('components.Queue.next'), next: t('components.Queue.label.next'),
pause: t('components.Queue.pause'), pause: t('components.Queue.label.pause'),
play: t('components.Queue.play'), play: t('components.Queue.label.play'),
fullscreen: t('components.Queue.enterFullscreen'), fullscreen: t('components.Queue.label.enterFullscreen'),
exitFullscreen: t('components.Queue.exitFullscreen'), exitFullscreen: t('components.Queue.label.exitFullscreen'),
showCoverArt: t('components.Queue.showCoverArt'), showCoverArt: t('components.Queue.label.showCoverArt'),
showVisualizer: t('components.Queue.showVisualizer') showVisualizer: t('components.Queue.label.showVisualizer')
})) }))
watchEffect(async () => { watchEffect(async () => {
@ -126,9 +126,9 @@ const queueItems = computed(() => queue.value.map((track, index) => ({
...track, ...track,
key: `${index}-${track.id}`, key: `${index}-${track.id}`,
labels: { labels: {
remove: t('components.Queue.remove'), remove: t('components.Queue.label.remove'),
selectTrack: t('components.Queue.selectTrack'), selectTrack: t('components.Queue.label.selectTrack'),
favorite: t('components.Queue.favorite') favorite: t('components.Queue.label.favorite')
}, },
duration: time.durationFormatted(track.uploads[0]?.duration ?? 0) ?? '' duration: time.durationFormatted(track.uploads[0]?.duration ?? 0) ?? ''
}) as QueueItemSource)) }) as QueueItemSource))
@ -298,14 +298,14 @@ const coverType = useStorage('queue:cover-type', CoverType.COVER_ART)
class="ui small warning message" class="ui small warning message"
> >
<h3 class="header"> <h3 class="header">
{{ $t('components.Queue.trackLoadFailure') }} {{ $t('components.Queue.header.failure') }}
</h3> </h3>
<p v-if="hasNext && isPlaying"> <p v-if="hasNext && isPlaying">
{{ $t('components.Queue.automaticPlay') }} {{ $t('components.Queue.message.automaticPlay') }}
<i class="loading spinner icon" /> <i class="loading spinner icon" />
</p> </p>
<p> <p>
{{ $t('components.Queue.connectivityWarning') }} {{ $t('components.Queue.warning.connectivity') }}
</p> </p>
</div> </div>
<div <div
@ -404,18 +404,18 @@ const coverType = useStorage('queue:cover-type', CoverType.COVER_ART)
class="ui right floated basic button" class="ui right floated basic button"
@click="$store.commit('ui/queueFocused', null)" @click="$store.commit('ui/queueFocused', null)"
> >
{{ $t('components.Queue.closeButton') }} {{ $t('components.Queue.button.close') }}
</button> </button>
<button <button
class="ui right floated basic button danger" class="ui right floated basic button danger"
@click="clear" @click="clear"
> >
{{ $t('components.Queue.clearButton') }} {{ $t('components.Queue.button.clear') }}
</button> </button>
{{ labels.queue }} {{ labels.queue }}
<div class="sub header"> <div class="sub header">
<div> <div>
{{ $t('components.Queue.queuePosition', {index: currentIndex +1, length: queue.length}) }} {{ $t('components.Queue.display.queuePosition', {index: currentIndex +1, length: queue.length}) }}
<template v-if="!$store.state.radios.running"> <template v-if="!$store.state.radios.running">
<span class="middle ellipses symbol" /> <span class="middle ellipses symbol" />
<span :title="labels.duration"> <span :title="labels.duration">
@ -461,10 +461,10 @@ const coverType = useStorage('queue:cover-type', CoverType.COVER_ART)
<div class="content"> <div class="content">
<h3 class="header"> <h3 class="header">
<i class="feed icon" /> <i class="feed icon" />
{{ $t('components.Queue.radioPlaying') }} {{ $t('components.Queue.header.radio') }}
</h3> </h3>
<p> <p>
{{ $t('components.Queue.appendTracks') }} {{ $t('components.Queue.message.radio') }}
</p> </p>
<button <button
class="ui basic primary button" class="ui basic primary button"

View File

@ -40,14 +40,14 @@ const errors = ref([] as string[])
const { t } = useI18n() const { t } = useI18n()
const labels = computed(() => ({ const labels = computed(() => ({
title: type.value === 'rss' title: type.value === 'rss'
? t('components.RemoteSearchForm.subscribeRss') ? t('components.RemoteSearchForm.label.rss.title')
: t('components.RemoteSearchForm.subscribeFediverse'), : t('components.RemoteSearchForm.label.fediverse.title'),
fieldLabel: type.value === 'rss' fieldLabel: type.value === 'rss'
? t('components.RemoteSearchForm.rssLocation') ? t('components.RemoteSearchForm.label.rss.fieldLabel')
: t('components.RemoteSearchForm.fediverseObject'), : t('components.RemoteSearchForm.label.fediverse.fieldLabel'),
fieldPlaceholder: type.value === 'rss' fieldPlaceholder: type.value === 'rss'
? t('components.RemoteSearchForm.rssPlaceholder') ? t('components.RemoteSearchForm.label.rss.fieldPlaceholder')
: t('components.RemoteSearchForm.fediversePlaceholder') : t('components.RemoteSearchForm.label.fediverse.fieldPlaceholder')
})) }))
const obj = ref() const obj = ref()
@ -117,7 +117,7 @@ const createFetch = async () => {
obj.value = response.data obj.value = response.data
if (response.data.status === 'errored' || response.data.status === 'skipped') { if (response.data.status === 'errored' || response.data.status === 'skipped') {
errors.value.push(t('components.RemoteSearchForm.fetchFailureMessage')) errors.value.push(t('components.RemoteSearchForm.error.fetchFailed'))
} }
} catch (error) { } catch (error) {
errors.value = (error as BackendError).backendErrors errors.value = (error as BackendError).backendErrors
@ -172,7 +172,7 @@ watch(() => props.initialId, () => {
@click.prevent="type = 'rss'" @click.prevent="type = 'rss'"
> >
<i class="feed icon" /> <i class="feed icon" />
{{ $t('components.RemoteSearchForm.rss') }} {{ $t('components.RemoteSearchForm.button.rss') }}
</button> </button>
<div class="or" /> <div class="or" />
<button <button
@ -180,7 +180,7 @@ watch(() => props.initialId, () => {
@click.prevent="type = 'artists'" @click.prevent="type = 'artists'"
> >
<i class="globe icon" /> <i class="globe icon" />
{{ $t('components.RemoteSearchForm.fediverse') }} {{ $t('components.RemoteSearchForm.button.fediverse') }}
</button> </button>
</div> </div>
<div v-else> <div v-else>
@ -195,7 +195,7 @@ watch(() => props.initialId, () => {
class="ui negative message" class="ui negative message"
> >
<h3 class="header"> <h3 class="header">
{{ $t('components.RemoteSearchForm.objectFetchError') }} {{ $t('components.RemoteSearchForm.header.fetchFailed') }}
</h3> </h3>
<ul class="list"> <ul class="list">
<li <li
@ -211,10 +211,10 @@ watch(() => props.initialId, () => {
{{ labels.fieldLabel }} {{ labels.fieldLabel }}
</label> </label>
<p v-if="type === 'rss'"> <p v-if="type === 'rss'">
{{ $t('components.RemoteSearchForm.rssDescription') }} {{ $t('components.RemoteSearchForm.description.rss') }}
</p> </p>
<p v-else-if="type === 'artists'"> <p v-else-if="type === 'artists'">
{{ $t('components.RemoteSearchForm.fediverseDescription') }} {{ $t('components.RemoteSearchForm.description.fediverse') }}
</p> </p>
<input <input
id="object-id" id="object-id"
@ -231,7 +231,7 @@ watch(() => props.initialId, () => {
:class="['ui', 'primary', {loading: isLoading}, 'button']" :class="['ui', 'primary', {loading: isLoading}, 'button']"
:disabled="isLoading || !id || id.length === 0" :disabled="isLoading || !id || id.length === 0"
> >
{{ $t('components.RemoteSearchForm.searchButton') }} {{ $t('components.RemoteSearchForm.button.search') }}
</button> </button>
</form> </form>
<div <div
@ -240,7 +240,7 @@ watch(() => props.initialId, () => {
class="ui warning message" class="ui warning message"
> >
<p> <p>
{{ $t('components.RemoteSearchForm.unsupportedObject') }} {{ $t('components.RemoteSearchForm.warning.unsupported') }}
</p> </p>
</div> </div>
</div> </div>

View File

@ -51,7 +51,7 @@ const checkAndSwitch = async (url: string) => {
show.value = false show.value = false
store.commit('ui/addMessage', { store.commit('ui/addMessage', {
content: t('components.SetInstanceModal.currentUrl', { url: instanceUrl }), content: t('components.SetInstanceModal.message.newUrl', { url: instanceUrl }),
date: new Date() date: new Date()
}) })
@ -71,7 +71,7 @@ const checkAndSwitch = async (url: string) => {
@update:show="isError = false" @update:show="isError = false"
> >
<h3 class="header"> <h3 class="header">
{{ $t('components.SetInstanceModal.chooseInstance') }} {{ $t('components.SetInstanceModal.header.chooseInstance') }}
</h3> </h3>
<div class="scrolling content"> <div class="scrolling content">
<div <div
@ -80,14 +80,14 @@ const checkAndSwitch = async (url: string) => {
class="ui negative message" class="ui negative message"
> >
<h4 class="header"> <h4 class="header">
{{ $t('components.SetInstanceModal.connectionFailure') }} {{ $t('components.SetInstanceModal.header.failure') }}
</h4> </h4>
<ul class="list"> <ul class="list">
<li> <li>
{{ $t('components.SetInstanceModal.serverDown') }} {{ $t('components.SetInstanceModal.help.serverDown') }}
</li> </li>
<li> <li>
{{ $t('components.SetInstanceModal.notFunkwhaleServer') }} {{ $t('components.SetInstanceModal.help.notFunkwhaleServer') }}
</li> </li>
</ul> </ul>
</div> </div>
@ -99,13 +99,13 @@ const checkAndSwitch = async (url: string) => {
v-if="$store.state.instance.instanceUrl" v-if="$store.state.instance.instanceUrl"
class="description" class="description"
> >
{{ $t('components.SetInstanceModal.currentConnection', {url: $store.state.instance.instanceUrl, hostname: $store.getters['instance/domain']}) }} {{ $t('components.SetInstanceModal.message.currentConnection', {url: $store.state.instance.instanceUrl, hostname: $store.getters['instance/domain']}) }}
</p> </p>
<p v-else> <p v-else>
{{ $t('components.SetInstanceModal.selectFunkwhalePod') }} {{ $t('components.SetInstanceModal.help.selectPod') }}
</p> </p>
<div class="field"> <div class="field">
<label for="instance-picker">{{ $t('components.SetInstanceModal.instanceUrl') }}</label> <label for="instance-picker">{{ $t('components.SetInstanceModal.label.url') }}</label>
<div class="ui action input"> <div class="ui action input">
<input <input
id="instance-picker" id="instance-picker"
@ -117,7 +117,7 @@ const checkAndSwitch = async (url: string) => {
type="submit" type="submit"
:class="['ui', 'icon', {loading: isLoading}, 'button']" :class="['ui', 'icon', {loading: isLoading}, 'button']"
> >
{{ $t('components.SetInstanceModal.submitButton') }} {{ $t('components.SetInstanceModal.button.submit') }}
</button> </button>
</div> </div>
</div> </div>
@ -129,7 +129,7 @@ const checkAndSwitch = async (url: string) => {
> >
<div class="field"> <div class="field">
<h4> <h4>
{{ $t('components.SetInstanceModal.suggestions') }} {{ $t('components.SetInstanceModal.header.suggestions') }}
</h4> </h4>
<button <button
v-for="(url, key) in suggestedInstances" v-for="(url, key) in suggestedInstances"
@ -144,7 +144,7 @@ const checkAndSwitch = async (url: string) => {
</div> </div>
<div class="actions"> <div class="actions">
<button class="ui basic cancel button"> <button class="ui basic cancel button">
{{ $t('components.SetInstanceModal.cancelButton') }} {{ $t('components.SetInstanceModal.button.cancel') }}
</button> </button>
</div> </div>
</semantic-modal> </semantic-modal>

View File

@ -20,19 +20,19 @@ const showRef = useVModel(props, 'show', emit)
const { t } = useI18n() const { t } = useI18n()
const general = computed(() => [ const general = computed(() => [
{ {
title: t('components.ShortcutsModal.generalShortcuts'), title: t('components.ShortcutsModal.shortcut.general.label'),
shortcuts: [ shortcuts: [
{ {
key: 'h', key: 'h',
summary: t('components.ShortcutsModal.showShortcuts') summary: t('components.ShortcutsModal.shortcut.general.show')
}, },
{ {
key: 'shift + f', key: 'shift + f',
summary: t('components.ShortcutsModal.focusSearch') summary: t('components.ShortcutsModal.shortcut.general.focus')
}, },
{ {
key: 'esc', key: 'esc',
summary: t('components.ShortcutsModal.unfocusSearch') summary: t('components.ShortcutsModal.shortcut.general.unfocus')
} }
] ]
} }
@ -40,67 +40,67 @@ const general = computed(() => [
const player = computed(() => [ const player = computed(() => [
{ {
title: t('components.ShortcutsModal.audioShortcuts'), title: t('components.ShortcutsModal.shortcut.audio.label'),
shortcuts: [ shortcuts: [
{ {
key: 'p', key: 'p',
summary: t('components.ShortcutsModal.playPause') summary: t('components.ShortcutsModal.shortcut.audio.playPause')
}, },
{ {
key: 'left', key: 'left',
summary: t('components.ShortcutsModal.seekBack5') summary: t('components.ShortcutsModal.shortcut.audio.seekBack5')
}, },
{ {
key: 'right', key: 'right',
summary: t('components.ShortcutsModal.seekForward5') summary: t('components.ShortcutsModal.shortcut.audio.seekForward5')
}, },
{ {
key: 'shift + left', key: 'shift + left',
summary: t('components.ShortcutsModal.seekBack30') summary: t('components.ShortcutsModal.shortcut.audio.seekBack30')
}, },
{ {
key: 'shift + right', key: 'shift + right',
summary: t('components.ShortcutsModal.seekForward30') summary: t('components.ShortcutsModal.shortcut.audio.seekForward30')
}, },
{ {
key: 'ctrl + shift + left', key: 'ctrl + shift + left',
summary: t('components.ShortcutsModal.playPrevious') summary: t('components.ShortcutsModal.shortcut.audio.playPrevious')
}, },
{ {
key: 'ctrl + shift + right', key: 'ctrl + shift + right',
summary: t('components.ShortcutsModal.playNext') summary: t('components.ShortcutsModal.shortcut.audio.playNext')
}, },
{ {
key: 'shift + up', key: 'shift + up',
summary: t('components.ShortcutsModal.increaseVolume') summary: t('components.ShortcutsModal.shortcut.audio.increaseVolume')
}, },
{ {
key: 'shift + down', key: 'shift + down',
summary: t('components.ShortcutsModal.decreaseVolume') summary: t('components.ShortcutsModal.shortcut.audio.decreaseVolume')
}, },
{ {
key: 'm', key: 'm',
summary: t('components.ShortcutsModal.toggleMute') summary: t('components.ShortcutsModal.shortcut.audio.toggleMute')
}, },
{ {
key: 'e', key: 'e',
summary: t('components.ShortcutsModal.expandQueue') summary: t('components.ShortcutsModal.shortcut.audio.expandQueue')
}, },
{ {
key: 'l', key: 'l',
summary: t('components.ShortcutsModal.toggleLoop') summary: t('components.ShortcutsModal.shortcut.audio.toggleLoop')
}, },
{ {
key: 's', key: 's',
summary: t('components.ShortcutsModal.shuffleQueue') summary: t('components.ShortcutsModal.shortcut.audio.shuffleQueue')
}, },
{ {
key: 'q', key: 'q',
summary: t('components.ShortcutsModal.clearQueue') summary: t('components.ShortcutsModal.shortcut.audio.clearQueue')
}, },
{ {
key: 'f', key: 'f',
summary: t('components.ShortcutsModal.toggleFavorite') summary: t('components.ShortcutsModal.shortcut.audio.toggleFavorite')
} }
] ]
} }
@ -110,7 +110,7 @@ const player = computed(() => [
<template> <template>
<semantic-modal v-model:show="showRef"> <semantic-modal v-model:show="showRef">
<header class="header"> <header class="header">
{{ $t('components.ShortcutsModal.modalHeader') }} {{ $t('components.ShortcutsModal.header.modal') }}
</header> </header>
<section class="scrolling content"> <section class="scrolling content">
<div class="ui stackable two column grid"> <div class="ui stackable two column grid">
@ -154,7 +154,7 @@ const player = computed(() => [
</section> </section>
<footer class="actions"> <footer class="actions">
<button class="ui basic cancel button"> <button class="ui basic cancel button">
{{ $t('components.ShortcutsModal.closeButton') }} {{ $t('components.ShortcutsModal.button.close') }}
</button> </button>
</footer> </footer>
</semantic-modal> </semantic-modal>

View File

@ -42,15 +42,15 @@ const additionalNotifications = computed(() => store.getters['ui/additionalNotif
const logoUrl = computed(() => store.state.auth.authenticated ? 'library.index' : 'index') const logoUrl = computed(() => store.state.auth.authenticated ? 'library.index' : 'index')
const labels = computed(() => ({ const labels = computed(() => ({
mainMenu: t('components.Sidebar.mainMenu'), mainMenu: t('components.Sidebar.label.main'),
selectTrack: t('components.Sidebar.selectTrack'), selectTrack: t('components.Sidebar.label.play'),
pendingFollows: t('components.Sidebar.pendingFollows'), pendingFollows: t('components.Sidebar.label.follows'),
pendingReviewEdits: t('components.Sidebar.pendingReviewEdits'), pendingReviewEdits: t('components.Sidebar.label.edits'),
pendingReviewReports: t('components.Sidebar.pendingReviewReports'), pendingReviewReports: t('components.Sidebar.label.reports'),
language: t('components.Sidebar.language'), language: t('components.Sidebar.label.language'),
theme: t('components.Sidebar.theme'), theme: t('components.Sidebar.label.theme'),
addContent: t('components.Sidebar.addContent'), addContent: t('components.Sidebar.label.add'),
administration: t('components.Sidebar.administration') administration: t('components.Sidebar.label.administration')
})) }))
type SidebarMenuTabs = 'explore' | 'myLibrary' type SidebarMenuTabs = 'explore' | 'myLibrary'
@ -129,7 +129,7 @@ onMounted(() => {
> >
<i class="logo bordered inverted vibrant big icon"> <i class="logo bordered inverted vibrant big icon">
<logo class="logo" /> <logo class="logo" />
<span class="visually-hidden">{{ $t('components.Sidebar.home') }}</span> <span class="visually-hidden">{{ $t('components.Sidebar.link.home') }}</span>
</i> </i>
</router-link> </router-link>
<nav class="top ui compact right aligned inverted text menu"> <nav class="top ui compact right aligned inverted text menu">
@ -149,7 +149,7 @@ onMounted(() => {
</div> </div>
<div class="menu"> <div class="menu">
<h3 class="header"> <h3 class="header">
{{ $t('components.Sidebar.administration') }} {{ $t('components.Sidebar.header.administration') }}
</h3> </h3>
<div class="divider" /> <div class="divider" />
<router-link <router-link
@ -164,7 +164,7 @@ onMounted(() => {
> >
{{ $store.state.ui.notifications.pendingReviewEdits }} {{ $store.state.ui.notifications.pendingReviewEdits }}
</div> </div>
{{ $t('components.Sidebar.library') }} {{ $t('components.Sidebar.link.library') }}
</router-link> </router-link>
<router-link <router-link
v-if="$store.state.auth.availablePermissions['moderation']" v-if="$store.state.auth.availablePermissions['moderation']"
@ -178,21 +178,21 @@ onMounted(() => {
> >
{{ $store.state.ui.notifications.pendingReviewReports + $store.state.ui.notifications.pendingReviewRequests }} {{ $store.state.ui.notifications.pendingReviewReports + $store.state.ui.notifications.pendingReviewRequests }}
</div> </div>
{{ $t('components.Sidebar.moderation') }} {{ $t('components.Sidebar.link.moderation') }}
</router-link> </router-link>
<router-link <router-link
v-if="$store.state.auth.availablePermissions['settings']" v-if="$store.state.auth.availablePermissions['settings']"
class="item" class="item"
:to="{name: 'manage.users.users.list'}" :to="{name: 'manage.users.users.list'}"
> >
{{ $t('components.Sidebar.users') }} {{ $t('components.Sidebar.link.users') }}
</router-link> </router-link>
<router-link <router-link
v-if="$store.state.auth.availablePermissions['settings']" v-if="$store.state.auth.availablePermissions['settings']"
class="item" class="item"
:to="{path: '/manage/settings'}" :to="{path: '/manage/settings'}"
> >
{{ $t('components.Sidebar.settings') }} {{ $t('components.Sidebar.link.settings') }}
</router-link> </router-link>
</div> </div>
</div> </div>
@ -352,14 +352,14 @@ onMounted(() => {
class="ui fluid tiny primary button" class="ui fluid tiny primary button"
:to="{name: 'login'}" :to="{name: 'login'}"
> >
{{ $t('components.Sidebar.login') }} {{ $t('components.Sidebar.link.login') }}
</router-link> </router-link>
<div class="ui small hidden divider" /> <div class="ui small hidden divider" />
<router-link <router-link
class="ui fluid tiny button" class="ui fluid tiny button"
:to="{path: '/signup'}" :to="{path: '/signup'}"
> >
{{ $t('components.Sidebar.createAccount') }} {{ $t('components.Sidebar.link.createAccount') }}
</router-link> </router-link>
</div> </div>
<nav <nav
@ -371,7 +371,7 @@ onMounted(() => {
id="navigation-label" id="navigation-label"
class="visually-hidden" class="visually-hidden"
> >
{{ $t('components.Sidebar.mainNavigation') }} {{ $t('components.Sidebar.header.main') }}
</h1> </h1>
<div class="ui small hidden divider" /> <div class="ui small hidden divider" />
<section <section
@ -391,7 +391,7 @@ onMounted(() => {
@click="expanded = 'explore'" @click="expanded = 'explore'"
@focus="expanded = 'explore'" @focus="expanded = 'explore'"
> >
{{ $t('components.Sidebar.explore') }} {{ $t('components.Sidebar.header.explore') }}
<i <i
v-if="expanded !== 'explore'" v-if="expanded !== 'explore'"
class="angle right icon" class="angle right icon"
@ -403,7 +403,7 @@ onMounted(() => {
:to="{name: 'search'}" :to="{name: 'search'}"
> >
<i class="search icon" /> <i class="search icon" />
{{ $t('components.Sidebar.search') }} {{ $t('components.Sidebar.link.search') }}
</router-link> </router-link>
<router-link <router-link
class="item" class="item"
@ -411,42 +411,42 @@ onMounted(() => {
active-class="_active" active-class="_active"
> >
<i class="music icon" /> <i class="music icon" />
{{ $t('components.Sidebar.browse') }} {{ $t('components.Sidebar.link.browse') }}
</router-link> </router-link>
<router-link <router-link
class="item" class="item"
:to="{name: 'library.podcasts.browse'}" :to="{name: 'library.podcasts.browse'}"
> >
<i class="podcast icon" /> <i class="podcast icon" />
{{ $t('components.Sidebar.podcasts') }} {{ $t('components.Sidebar.link.podcasts') }}
</router-link> </router-link>
<router-link <router-link
class="item" class="item"
:to="{name: 'library.albums.browse'}" :to="{name: 'library.albums.browse'}"
> >
<i class="compact disc icon" /> <i class="compact disc icon" />
{{ $t('components.Sidebar.albums') }} {{ $t('components.Sidebar.link.albums') }}
</router-link> </router-link>
<router-link <router-link
class="item" class="item"
:to="{name: 'library.artists.browse'}" :to="{name: 'library.artists.browse'}"
> >
<i class="user icon" /> <i class="user icon" />
{{ $t('components.Sidebar.artists') }} {{ $t('components.Sidebar.link.artists') }}
</router-link> </router-link>
<router-link <router-link
class="item" class="item"
:to="{name: 'library.playlists.browse'}" :to="{name: 'library.playlists.browse'}"
> >
<i class="list icon" /> <i class="list icon" />
{{ $t('components.Sidebar.playlists') }} {{ $t('components.Sidebar.link.playlists') }}
</router-link> </router-link>
<router-link <router-link
class="item" class="item"
:to="{name: 'library.radios.browse'}" :to="{name: 'library.radios.browse'}"
> >
<i class="feed icon" /> <i class="feed icon" />
{{ $t('components.Sidebar.radios') }} {{ $t('components.Sidebar.link.radios') }}
</router-link> </router-link>
</div> </div>
</div> </div>
@ -461,7 +461,7 @@ onMounted(() => {
@click="expanded = 'myLibrary'" @click="expanded = 'myLibrary'"
@focus="expanded = 'myLibrary'" @focus="expanded = 'myLibrary'"
> >
{{ $t('components.Sidebar.myLibrary') }} {{ $t('components.Sidebar.header.library') }}
<i <i
v-if="expanded !== 'myLibrary'" v-if="expanded !== 'myLibrary'"
class="angle right icon" class="angle right icon"
@ -473,42 +473,42 @@ onMounted(() => {
:to="{name: 'library.me'}" :to="{name: 'library.me'}"
> >
<i class="music icon" /> <i class="music icon" />
{{ $t('components.Sidebar.browse') }} {{ $t('components.Sidebar.link.browse') }}
</router-link> </router-link>
<router-link <router-link
class="item" class="item"
:to="{name: 'library.albums.me'}" :to="{name: 'library.albums.me'}"
> >
<i class="compact disc icon" /> <i class="compact disc icon" />
{{ $t('components.Sidebar.albums') }} {{ $t('components.Sidebar.link.albums') }}
</router-link> </router-link>
<router-link <router-link
class="item" class="item"
:to="{name: 'library.artists.me'}" :to="{name: 'library.artists.me'}"
> >
<i class="user icon" /> <i class="user icon" />
{{ $t('components.Sidebar.artists') }} {{ $t('components.Sidebar.link.artists') }}
</router-link> </router-link>
<router-link <router-link
class="item" class="item"
:to="{name: 'library.playlists.me'}" :to="{name: 'library.playlists.me'}"
> >
<i class="list icon" /> <i class="list icon" />
{{ $t('components.Sidebar.playlists') }} {{ $t('components.Sidebar.link.playlists') }}
</router-link> </router-link>
<router-link <router-link
class="item" class="item"
:to="{name: 'library.radios.me'}" :to="{name: 'library.radios.me'}"
> >
<i class="feed icon" /> <i class="feed icon" />
{{ $t('components.Sidebar.radios') }} {{ $t('components.Sidebar.link.radios') }}
</router-link> </router-link>
<router-link <router-link
class="item" class="item"
:to="{name: 'favorites'}" :to="{name: 'favorites'}"
> >
<i class="heart icon" /> <i class="heart icon" />
{{ $t('components.Sidebar.favorites') }} {{ $t('components.Sidebar.link.favorites') }}
</router-link> </router-link>
</div> </div>
</div> </div>
@ -517,11 +517,11 @@ onMounted(() => {
class="header item" class="header item"
:to="{name: 'subscriptions'}" :to="{name: 'subscriptions'}"
> >
{{ $t('components.Sidebar.channels') }} {{ $t('components.Sidebar.link.channels') }}
</router-link> </router-link>
<div class="item"> <div class="item">
<h3 class="header"> <h3 class="header">
{{ $t('components.Sidebar.more') }} {{ $t('components.Sidebar.header.more') }}
</h3> </h3>
<div class="menu"> <div class="menu">
<router-link <router-link
@ -530,7 +530,7 @@ onMounted(() => {
active-class="router-link-exact-active active" active-class="router-link-exact-active active"
> >
<i class="info icon" /> <i class="info icon" />
{{ $t('components.Sidebar.aboutPod') }} {{ $t('components.Sidebar.link.about') }}
</router-link> </router-link>
</div> </div>
</div> </div>
@ -543,7 +543,7 @@ onMounted(() => {
href="" href=""
class="link item" class="link item"
@click.prevent="emit('show:set-instance-modal')" @click.prevent="emit('show:set-instance-modal')"
>{{ $t('components.Sidebar.switchInstance') }}</a> >{{ $t('components.Sidebar.link.switchInstance') }}</a>
</div> </div>
</nav> </nav>
</section> </section>

View File

@ -110,7 +110,7 @@ const save = async () => {
class="ui negative message" class="ui negative message"
> >
<h4 class="header"> <h4 class="header">
{{ $t('components.admin.SettingsGroup.errorMessage') }} {{ $t('components.admin.SettingsGroup.header.error') }}
</h4> </h4>
<ul class="list"> <ul class="list">
<li <li
@ -125,7 +125,7 @@ const save = async () => {
v-if="result" v-if="result"
class="ui positive message" class="ui positive message"
> >
{{ $t('components.admin.SettingsGroup.successMessage') }} {{ $t('components.admin.SettingsGroup.message.success') }}
</div> </div>
<div <div
v-for="(setting, key) in settings" v-for="(setting, key) in settings"
@ -225,7 +225,7 @@ const save = async () => {
<div v-if="values[setting.identifier]"> <div v-if="values[setting.identifier]">
<div class="ui hidden divider" /> <div class="ui hidden divider" />
<h3 class="ui header"> <h3 class="ui header">
{{ $t('components.admin.SettingsGroup.currentImage') }} {{ $t('components.admin.SettingsGroup.header.image') }}
</h3> </h3>
<img <img
v-if="values[setting.identifier]" v-if="values[setting.identifier]"
@ -240,7 +240,7 @@ const save = async () => {
type="submit" type="submit"
:class="['ui', {'loading': isLoading}, 'right', 'floated', 'success', 'button']" :class="['ui', {'loading': isLoading}, 'right', 'floated', 'success', 'button']"
> >
{{ $t('components.admin.SettingsGroup.saveButton') }} {{ $t('components.admin.SettingsGroup.button.save') }}
</button> </button>
</form> </form>
</template> </template>

View File

@ -28,9 +28,9 @@ const isPreviewing = ref(false)
const { t } = useI18n() const { t } = useI18n()
const labels = computed(() => ({ const labels = computed(() => ({
delete: t('components.admin.SignupFormBuilder.deleteLabel'), delete: t('components.admin.SignupFormBuilder.label.delete'),
up: t('components.admin.SignupFormBuilder.moveUpLabel'), up: t('components.admin.SignupFormBuilder.label.moveUp'),
down: t('components.admin.SignupFormBuilder.moveDownLabel') down: t('components.admin.SignupFormBuilder.label.moveDown')
})) }))
if (!value.value?.fields) { if (!value.value?.fields) {
@ -45,7 +45,7 @@ if (!value.value?.fields) {
const addField = () => { const addField = () => {
value.value.fields.push({ value.value.fields.push({
label: t('components.admin.SignupFormBuilder.additionalFieldInput') + ' ' + (value.value.fields.length + 1), label: t('components.admin.SignupFormBuilder.label.additionalField') + ' ' + (value.value.fields.length + 1),
required: true, required: true,
input_type: 'short_text' input_type: 'short_text'
}) })
@ -69,13 +69,13 @@ const move = (idx: number, increment: number) => {
:class="[{active: !isPreviewing}, 'item']" :class="[{active: !isPreviewing}, 'item']"
@click.stop.prevent="isPreviewing = false" @click.stop.prevent="isPreviewing = false"
> >
{{ $t('components.admin.SignupFormBuilder.editForm') }} {{ $t('components.admin.SignupFormBuilder.button.edit') }}
</button> </button>
<button <button
:class="[{active: isPreviewing}, 'item']" :class="[{active: isPreviewing}, 'item']"
@click.stop.prevent="isPreviewing = true" @click.stop.prevent="isPreviewing = true"
> >
{{ $t('components.admin.SignupFormBuilder.previewForm') }} {{ $t('components.admin.SignupFormBuilder.button.preview') }}
</button> </button>
</div> </div>
<div <div
@ -95,10 +95,10 @@ const move = (idx: number, increment: number) => {
> >
<div class="field"> <div class="field">
<label for="help-text"> <label for="help-text">
{{ $t('components.admin.SignupFormBuilder.helpTextLabel') }} {{ $t('components.admin.SignupFormBuilder.label.helpText') }}
</label> </label>
<p> <p>
{{ $t('components.admin.SignupFormBuilder.helpTextMessage') }} {{ $t('components.admin.SignupFormBuilder.help.helpText') }}
</p> </p>
<content-form <content-form
v-if="value.help_text" v-if="value.help_text"
@ -109,24 +109,24 @@ const move = (idx: number, increment: number) => {
</div> </div>
<div class="field"> <div class="field">
<label> <label>
{{ $t('components.admin.SignupFormBuilder.additionalFieldsLabel') }} {{ $t('components.admin.SignupFormBuilder.label.additionalFields') }}
</label> </label>
<p> <p>
{{ $t('components.admin.SignupFormBuilder.additionalFieldsMessage') }} {{ $t('components.admin.SignupFormBuilder.help.additionalFields') }}
</p> </p>
<table v-if="value.fields?.length > 0"> <table v-if="value.fields?.length > 0">
<thead> <thead>
<tr> <tr>
<th> <th>
{{ $t('components.admin.SignupFormBuilder.fieldLabelTableHeader') }} {{ $t('components.admin.SignupFormBuilder.table.additionalFields.header.label') }}
</th> </th>
<th> <th>
{{ $t('components.admin.SignupFormBuilder.fieldTypeTableHeader') }} {{ $t('components.admin.SignupFormBuilder.table.additionalFields.header.type') }}
</th> </th>
<th> <th>
{{ $t('components.admin.SignupFormBuilder.requiredTableHeader') }} {{ $t('components.admin.SignupFormBuilder.table.additionalFields.header.required') }}
</th> </th>
<th><span class="visually-hidden">{{ $t('components.admin.SignupFormBuilder.actionsTableHeader') }}</span></th> <th><span class="visually-hidden">{{ $t('components.admin.SignupFormBuilder.table.additionalFields.header.actions') }}</span></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -144,20 +144,20 @@ const move = (idx: number, increment: number) => {
<td> <td>
<select v-model="field.input_type"> <select v-model="field.input_type">
<option value="short_text"> <option value="short_text">
{{ $t('components.admin.SignupFormBuilder.shortTextInput') }} {{ $t('components.admin.SignupFormBuilder.table.additionalFields.type.short') }}
</option> </option>
<option value="long_text"> <option value="long_text">
{{ $t('components.admin.SignupFormBuilder.longTextInput') }} {{ $t('components.admin.SignupFormBuilder.table.additionalFields.type.long') }}
</option> </option>
</select> </select>
</td> </td>
<td> <td>
<select v-model="field.required"> <select v-model="field.required">
<option :value="true"> <option :value="true">
{{ $t('components.admin.SignupFormBuilder.requiredTrue') }} {{ $t('components.admin.SignupFormBuilder.table.additionalFields.required.true') }}
</option> </option>
<option :value="false"> <option :value="false">
{{ $t('components.admin.SignupFormBuilder.requiredFalse') }} {{ $t('components.admin.SignupFormBuilder.table.additionalFields.required.false') }}
</option> </option>
</select> </select>
</td> </td>
@ -192,7 +192,7 @@ const move = (idx: number, increment: number) => {
class="ui basic button" class="ui basic button"
@click.stop.prevent="addField" @click.stop.prevent="addField"
> >
{{ $t('components.admin.SignupFormBuilder.addFieldButton') }} {{ $t('components.admin.SignupFormBuilder.button.add') }}
</button> </button>
</div> </div>
</div> </div>

View File

@ -33,7 +33,7 @@ const urlId = computed(() => props.object.actor?.is_local
const { t } = useI18n() const { t } = useI18n()
const updatedTitle = computed(() => { const updatedTitle = computed(() => {
const date = momentFormat(new Date(props.object.artist?.modification_date ?? '1970-01-01')) const date = momentFormat(new Date(props.object.artist?.modification_date ?? '1970-01-01'))
return t('components.audio.ChannelCard.updatedOn', { date }) return t('components.audio.ChannelCard.title', { date })
}) })
// TODO (wvffle): Use time ago // TODO (wvffle): Use time ago
@ -68,12 +68,12 @@ const updatedAgo = computed(() => moment(props.object.artist?.modification_date)
v-if="object.artist?.content_category === 'podcast'" v-if="object.artist?.content_category === 'podcast'"
class="meta ellipsis" class="meta ellipsis"
> >
{{ $t('components.audio.ChannelCard.episodeCount', {episode_count: object.artist.tracks_count}) }} {{ $t('components.audio.ChannelCard.meta.episodes', {episode_count: object.artist.tracks_count}) }}
</span> </span>
<span <span
v-else v-else
> >
{{ $t('components.audio.ChannelCard.trackCount', {tracks_count: object.artist?.tracks_count}) }} {{ $t('components.audio.ChannelCard.meta.tracks', {tracks_count: object.artist?.tracks_count}) }}
</span> </span>
<tags-list <tags-list
label-classes="tiny" label-classes="tiny"

View File

@ -103,7 +103,7 @@ watch(page, fetchData, { immediate: true })
@refresh="fetchData()" @refresh="fetchData()"
> >
<p> <p>
{{ $t('components.audio.ChannelEntries.emptyMessage') }} {{ $t('components.audio.ChannelEntries.help.subscribe') }}
</p> </p>
</empty-state> </empty-state>
</template> </template>

View File

@ -45,13 +45,13 @@ const creating = computed(() => props.object === null)
const categoryChoices = computed(() => [ const categoryChoices = computed(() => [
{ {
value: 'podcast', value: 'podcast',
label: t('components.audio.ChannelForm.podcastsLabel'), label: t('components.audio.ChannelForm.label.podcast'),
helpText: t('components.audio.ChannelForm.podcastsHelpText') helpText: t('components.audio.ChannelForm.help.podcast')
}, },
{ {
value: 'music', value: 'music',
label: t('components.audio.ChannelForm.discographyLabel'), label: t('components.audio.ChannelForm.label.discography'),
helpText: t('components.audio.ChannelForm.discographyHelpText') helpText: t('components.audio.ChannelForm.help.discography')
} }
]) ])
@ -81,8 +81,8 @@ const itunesSubcategories = computed(() => {
}) })
const labels = computed(() => ({ const labels = computed(() => ({
namePlaceholder: t('components.audio.ChannelForm.namePlaceholder'), namePlaceholder: t('components.audio.ChannelForm.placeholder.name'),
usernamePlaceholder: t('components.audio.ChannelForm.usernamePlaceholder') usernamePlaceholder: t('components.audio.ChannelForm.placeholder.username')
})) }))
const submittable = computed(() => !!( const submittable = computed(() => !!(
@ -165,7 +165,7 @@ defineExpose({
class="ui negative message" class="ui negative message"
> >
<h4 class="header"> <h4 class="header">
{{ $t('components.audio.ChannelForm.errorHeader') }} {{ $t('components.audio.ChannelForm.header.error') }}
</h4> </h4>
<ul class="list"> <ul class="list">
<li <li
@ -182,7 +182,7 @@ defineExpose({
class="ui grouped channel-type required field" class="ui grouped channel-type required field"
> >
<legend> <legend>
{{ $t('components.audio.ChannelForm.channelPurposeLegend') }} {{ $t('components.audio.ChannelForm.legend.purpose') }}
</legend> </legend>
<div class="ui hidden divider" /> <div class="ui hidden divider" />
<div class="field"> <div class="field">
@ -210,7 +210,7 @@ defineExpose({
<template v-if="!creating || step === 2"> <template v-if="!creating || step === 2">
<div class="ui required field"> <div class="ui required field">
<label for="channel-name"> <label for="channel-name">
{{ $t('components.audio.ChannelForm.channelNameLabel') }} {{ $t('components.audio.ChannelForm.label.name') }}
</label> </label>
<input <input
v-model="newValues.name" v-model="newValues.name"
@ -221,7 +221,7 @@ defineExpose({
</div> </div>
<div class="ui required field"> <div class="ui required field">
<label for="channel-username"> <label for="channel-username">
{{ $t('components.audio.ChannelForm.channelUsernameLabel') }} {{ $t('components.audio.ChannelForm.label.username') }}
</label> </label>
<div class="ui left labeled input"> <div class="ui left labeled input">
<div class="ui basic label"> <div class="ui basic label">
@ -238,7 +238,7 @@ defineExpose({
<template v-if="creating"> <template v-if="creating">
<div class="ui small hidden divider" /> <div class="ui small hidden divider" />
<p> <p>
{{ $t('components.audio.ChannelForm.channelUsernameDescription') }} {{ $t('components.audio.ChannelForm.help.username') }}
</p> </p>
</template> </template>
</div> </div>
@ -248,7 +248,7 @@ defineExpose({
:image-class="newValues.content_category === 'podcast' ? '' : 'circular'" :image-class="newValues.content_category === 'podcast' ? '' : 'circular'"
@delete="newValues.cover = null" @delete="newValues.cover = null"
> >
{{ $t('components.audio.ChannelForm.channelImageLabel') }} {{ $t('components.audio.ChannelForm.label.image') }}
</attachment-input> </attachment-input>
</div> </div>
<div class="ui small hidden divider" /> <div class="ui small hidden divider" />
@ -256,7 +256,7 @@ defineExpose({
<div class="ten wide column"> <div class="ten wide column">
<div class="ui field"> <div class="ui field">
<label for="channel-tags"> <label for="channel-tags">
{{ $t('components.audio.ChannelForm.channelTagsLabel') }} {{ $t('components.audio.ChannelForm.label.tags') }}
</label> </label>
<tags-selector <tags-selector
id="channel-tags" id="channel-tags"
@ -271,7 +271,7 @@ defineExpose({
> >
<div class="ui required field"> <div class="ui required field">
<label for="channel-language"> <label for="channel-language">
{{ $t('components.audio.ChannelForm.channelLanguageLabel') }} {{ $t('components.audio.ChannelForm.label.language') }}
</label> </label>
<select <select
id="channel-language" id="channel-language"
@ -294,7 +294,7 @@ defineExpose({
<div class="ui small hidden divider" /> <div class="ui small hidden divider" />
<div class="ui field"> <div class="ui field">
<label for="channel-name"> <label for="channel-name">
{{ $t('components.audio.ChannelForm.channelDescriptionLabel') }} {{ $t('components.audio.ChannelForm.label.description') }}
</label> </label>
<content-form v-model="newValues.description" /> <content-form v-model="newValues.description" />
</div> </div>
@ -304,7 +304,7 @@ defineExpose({
> >
<div class="ui required field"> <div class="ui required field">
<label for="channel-itunes-category"> <label for="channel-itunes-category">
{{ $t('components.audio.ChannelForm.channelCategoryLabel') }} {{ $t('components.audio.ChannelForm.label.category') }}
</label> </label>
<select <select
id="itunes-category" id="itunes-category"
@ -324,7 +324,7 @@ defineExpose({
</div> </div>
<div class="ui field"> <div class="ui field">
<label for="channel-itunes-category"> <label for="channel-itunes-category">
{{ $t('components.audio.ChannelForm.channelSubcategoryLabel') }} {{ $t('components.audio.ChannelForm.label.subcategory') }}
</label> </label>
<select <select
id="itunes-category" id="itunes-category"
@ -349,7 +349,7 @@ defineExpose({
> >
<div class="ui field"> <div class="ui field">
<label for="channel-itunes-email"> <label for="channel-itunes-email">
{{ $t('components.audio.ChannelForm.channelEmailLabel') }} {{ $t('components.audio.ChannelForm.label.email') }}
</label> </label>
<input <input
id="channel-itunes-email" id="channel-itunes-email"
@ -360,7 +360,7 @@ defineExpose({
</div> </div>
<div class="ui field"> <div class="ui field">
<label for="channel-itunes-name"> <label for="channel-itunes-name">
{{ $t('components.audio.ChannelForm.channelOwnerLabel') }} {{ $t('components.audio.ChannelForm.label.owner') }}
</label> </label>
<input <input
id="channel-itunes-name" id="channel-itunes-name"
@ -371,7 +371,7 @@ defineExpose({
</div> </div>
</div> </div>
<p> <p>
{{ $t('components.audio.ChannelForm.channelPodcastFieldsHelp') }} {{ $t('components.audio.ChannelForm.help.podcastFields') }}
</p> </p>
</template> </template>
</template> </template>
@ -380,7 +380,7 @@ defineExpose({
class="ui active inverted dimmer" class="ui active inverted dimmer"
> >
<div class="ui text loader"> <div class="ui text loader">
{{ $t('components.audio.ChannelForm.loadingMessage') }} {{ $t('components.audio.ChannelForm.message.loading') }}
</div> </div>
</div> </div>
</form> </form>

View File

@ -56,7 +56,7 @@ const cover = computed(() => props.serie?.cover ?? null)
</strong> </strong>
<div class="description"> <div class="description">
<span> <span>
{{ $t('components.audio.ChannelSerieCard.episodeCount', serie.tracks_count) }} {{ $t('components.audio.ChannelSerieCard.meta.episodes', serie.tracks_count) }}
</span> </span>
</div> </div>
</div> </div>

View File

@ -84,7 +84,7 @@ fetchData()
:class="['ui', 'basic', 'button']" :class="['ui', 'basic', 'button']"
@click="fetchData(nextPage)" @click="fetchData(nextPage)"
> >
{{ $t('components.audio.ChannelSeries.showMore') }} {{ $t('components.audio.ChannelSeries.button.showMore') }}
</button> </button>
</template> </template>
<template v-if="!isLoading && albums.length === 0"> <template v-if="!isLoading && albums.length === 0">
@ -93,7 +93,7 @@ fetchData()
@refresh="fetchData()" @refresh="fetchData()"
> >
<p> <p>
{{ $t('components.audio.ChannelSeries.emptyMessage') }} {{ $t('components.audio.ChannelSeries.help.subscribe') }}
</p> </p>
</empty-state> </empty-state>
</template> </template>

View File

@ -77,7 +77,7 @@ fetchData()
:class="['ui', 'basic', 'button']" :class="['ui', 'basic', 'button']"
@click="fetchData(nextPage)" @click="fetchData(nextPage)"
> >
{{ $t('components.audio.ChannelsWidget.showMore') }} {{ $t('components.audio.ChannelsWidget.button.showMore') }}
</button> </button>
</template> </template>
<template v-if="!isLoading && channels.length === 0"> <template v-if="!isLoading && channels.length === 0">

View File

@ -52,20 +52,20 @@ const { copy, copied } = useClipboard({ source: textarea })
> >
<p> <p>
<strong> <strong>
{{ $t('components.audio.EmbedWizard.anonymousAccessWarning') }} {{ $t('components.audio.EmbedWizard.warning.anonymous') }}
</strong> </strong>
</p> </p>
<p> <p>
{{ $t('components.audio.EmbedWizard.anonymousAccessHelp') }} {{ $t('components.audio.EmbedWizard.help.anonymous') }}
</p> </p>
</div> </div>
<div class="ui form"> <div class="ui form">
<div class="two fields"> <div class="two fields">
<div class="field"> <div class="field">
<div class="field"> <div class="field">
<label for="embed-width">{{ $t('components.audio.EmbedWizard.widgetWidthLabel') }}</label> <label for="embed-width">{{ $t('components.audio.EmbedWizard.label.width') }}</label>
<p> <p>
{{ $t('components.audio.EmbedWizard.widgetWidthHelp') }} {{ $t('components.audio.EmbedWizard.help.width') }}
</p> </p>
<input <input
id="embed-width" id="embed-width"
@ -78,7 +78,7 @@ const { copy, copied } = useClipboard({ source: textarea })
<template v-if="type != 'track'"> <template v-if="type != 'track'">
<br> <br>
<div class="field"> <div class="field">
<label for="embed-height">{{ $t('components.audio.EmbedWizard.widgetHeightLabel') }}</label> <label for="embed-height">{{ $t('components.audio.EmbedWizard.label.height') }}</label>
<input <input
id="embed-height" id="embed-height"
v-model="height" v-model="height"
@ -96,11 +96,11 @@ const { copy, copied } = useClipboard({ source: textarea })
@click="copy()" @click="copy()"
> >
<i class="copy icon" /> <i class="copy icon" />
{{ $t('components.audio.EmbedWizard.copyButton') }} {{ $t('components.audio.EmbedWizard.button.copy') }}
</button> </button>
<label for="embed-width">{{ $t('components.audio.EmbedWizard.embedCodeLabel') }}</label> <label for="embed-width">{{ $t('components.audio.EmbedWizard.label.embed') }}</label>
<p> <p>
{{ $t('components.audio.EmbedWizard.embedCodeHelp') }} {{ $t('components.audio.EmbedWizard.help.embed') }}
</p> </p>
<textarea <textarea
ref="textarea" ref="textarea"
@ -113,7 +113,7 @@ const { copy, copied } = useClipboard({ source: textarea })
v-if="copied" v-if="copied"
class="message" class="message"
> >
{{ $t('components.audio.EmbedWizard.copyButtonSuccessMessage') }} {{ $t('components.audio.EmbedWizard.message.copy') }}
</p> </p>
</div> </div>
</div> </div>
@ -125,7 +125,7 @@ const { copy, copied } = useClipboard({ source: textarea })
:href="iframeSrc" :href="iframeSrc"
target="_blank" target="_blank"
> >
{{ $t('components.audio.EmbedWizard.previewHeader') }} {{ $t('components.audio.EmbedWizard.header.preview') }}
</a> </a>
</h3> </h3>
<iframe <iframe

View File

@ -41,17 +41,17 @@ const toggle = () => {
<span <span
v-if="isApproved" v-if="isApproved"
> >
{{ $t('components.audio.LibraryFollowButton.unfollowLabel') }} {{ $t('components.audio.LibraryFollowButton.button.unfollow') }}
</span> </span>
<span <span
v-else-if="isPending" v-else-if="isPending"
> >
{{ $t('components.audio.LibraryFollowButton.cancelLabel') }} {{ $t('components.audio.LibraryFollowButton.button.cancel') }}
</span> </span>
<span <span
v-else v-else
> >
{{ $t('components.audio.LibraryFollowButton.followLabel') }} {{ $t('components.audio.LibraryFollowButton.button.follow') }}
</span> </span>
</button> </button>
</template> </template>

View File

@ -65,31 +65,31 @@ const { report, getReportableObjects } = useReport()
const { t } = useI18n() const { t } = useI18n()
const labels = computed(() => ({ const labels = computed(() => ({
playNow: t('components.audio.PlayButton.playNowLabel'), playNow: t('components.audio.PlayButton.button.playNow'),
addToQueue: t('components.audio.PlayButton.addToQueueLabel'), addToQueue: t('components.audio.PlayButton.button.addToQueue'),
playNext: t('components.audio.PlayButton.playNextLabel'), playNext: t('components.audio.PlayButton.button.playNext'),
startRadio: t('components.audio.PlayButton.startRadioLabel'), startRadio: t('components.audio.PlayButton.button.startRadio'),
report: t('components.audio.PlayButton.reportLabel'), report: t('components.audio.PlayButton.button.report'),
addToPlaylist: t('components.audio.PlayButton.addToPlaylistLabel'), addToPlaylist: t('components.audio.PlayButton.button.addToPlaylist'),
hideArtist: t('components.audio.PlayButton.hideArtistLabel'), hideArtist: t('components.audio.PlayButton.button.hideArtist'),
replacePlay: props.track replacePlay: props.track
? t('components.audio.PlayButton.playTrackLabel') ? t('components.audio.PlayButton.button.playTrack')
: props.album : props.album
? t('components.audio.PlayButton.playAlbumLabel') ? t('components.audio.PlayButton.button.playAlbum')
: props.artist : props.artist
? t('components.audio.PlayButton.playArtistLabel') ? t('components.audio.PlayButton.button.playArtist')
: props.playlist : props.playlist
? t('components.audio.PlayButton.playPlaylistLabel') ? t('components.audio.PlayButton.button.playPlaylist')
: t('components.audio.PlayButton.playTracksLabel') : t('components.audio.PlayButton.button.playTracks')
})) }))
const title = computed(() => { const title = computed(() => {
if (playable.value) { if (playable.value) {
return t('components.audio.PlayButton.moreTitle') return t('components.audio.PlayButton.title.more')
} }
if (props.track) { if (props.track) {
return t('components.audio.PlayButton.notAvailableTitle') return t('components.audio.PlayButton.title.unavailable')
} }
return '' return ''
@ -138,7 +138,7 @@ const openMenu = () => {
v-else v-else
:class="[playIconClass, 'icon']" :class="[playIconClass, 'icon']"
/> />
<template v-if="!discrete && !iconOnly">&nbsp;<slot>{{ $t('components.audio.PlayButton.discretePlayButton') }}</slot></template> <template v-if="!discrete && !iconOnly">&nbsp;<slot>{{ $t('components.audio.PlayButton.button.discretePlay') }}</slot></template>
</button> </button>
<button <button
v-if="!discrete && !iconOnly" v-if="!discrete && !iconOnly"
@ -200,10 +200,10 @@ const openMenu = () => {
<i class="info icon" /> <i class="info icon" />
<span <span
v-if="track.artist?.content_category === 'podcast'" v-if="track.artist?.content_category === 'podcast'"
>{{ $t('components.audio.PlayButton.episodeDetailsButton') }}</span> >{{ $t('components.audio.PlayButton.button.episodeDetails') }}</span>
<span <span
v-else v-else
>{{ $t('components.audio.PlayButton.trackDetailsButton') }}</span> >{{ $t('components.audio.PlayButton.button.trackDetails') }}</span>
</button> </button>
<div class="divider" /> <div class="divider" />
<button <button

View File

@ -72,17 +72,17 @@ onKeyboardShortcut(['ctrl', 'shift', 'left'], playPrevious, true)
onKeyboardShortcut(['ctrl', 'shift', 'right'], playNext, true) onKeyboardShortcut(['ctrl', 'shift', 'right'], playNext, true)
const labels = computed(() => ({ const labels = computed(() => ({
audioPlayer: t('components.audio.Player.audioPlayerLabel'), audioPlayer: t('components.audio.Player.label.audioPlayer'),
previous: t('components.audio.Player.previousTrackLabel'), previous: t('components.audio.Player.label.previousTrack'),
play: t('components.audio.Player.playLabel'), play: t('components.audio.Player.label.play'),
pause: t('components.audio.Player.pauseLabel'), pause: t('components.audio.Player.label.pause'),
next: t('components.audio.Player.nextTrackLabel'), next: t('components.audio.Player.label.nextTrack'),
unmute: t('components.audio.Player.unmuteLabel'), unmute: t('components.audio.Player.label.unmute'),
mute: t('components.audio.Player.muteLabel'), mute: t('components.audio.Player.label.mute'),
expandQueue: t('components.audio.Player.expandQueueLabel'), expandQueue: t('components.audio.Player.label.expandQueue'),
shuffle: t('components.audio.Player.shuffleQueueLabel'), shuffle: t('components.audio.Player.label.shuffleQueue'),
clear: t('components.audio.Player.clearQueueLabel'), clear: t('components.audio.Player.label.clearQueue'),
addArtistContentFilter: t('components.audio.Player.addArtistContentFilterLabel') addArtistContentFilter: t('components.audio.Player.label.addArtistContentFilter')
})) }))
const switchTab = () => { const switchTab = () => {
@ -103,10 +103,10 @@ initializeFirstTrack()
const loopingTitle = computed(() => { const loopingTitle = computed(() => {
const mode = looping.value const mode = looping.value
return mode === LoopingMode.None return mode === LoopingMode.None
? t('components.audio.Player.loopingDisabledLabel') ? t('components.audio.Player.label.loopingDisabledLabel')
: mode === LoopingMode.LoopTrack : mode === LoopingMode.LoopTrack
? t('components.audio.Player.loopingSingleLabel') ? t('components.audio.Player.label.loopingSingleLabel')
: t('components.audio.Player.loopingWholeQueueLabel') : t('components.audio.Player.label.loopingWholeQueueLabel')
}) })
const hideArtist = () => { const hideArtist = () => {
@ -133,7 +133,7 @@ const hideArtist = () => {
id="player-label" id="player-label"
class="visually-hidden" class="visually-hidden"
> >
{{ $t('components.audio.Player.playerHeader') }} {{ $t('components.audio.Player.header.player') }}
</h1> </h1>
<div <div
class="ui inverted segment fixed-controls" class="ui inverted segment fixed-controls"
@ -301,7 +301,7 @@ const hideArtist = () => {
> >
<i class="stream icon" /> <i class="stream icon" />
<span> <span>
{{ $t('components.audio.Player.queuePosition', { index: currentIndex + 1, length: queue.length }) }} {{ $t('components.audio.Player.meta.position', { index: currentIndex + 1, length: queue.length }) }}
</span> </span>
</button> </button>
<button <button
@ -310,7 +310,7 @@ const hideArtist = () => {
> >
<i class="stream icon" /> <i class="stream icon" />
<span> <span>
{{ $t('components.audio.Player.queuePosition', { index: currentIndex + 1, length: queue.length }) }} {{ $t('components.audio.Player.meta.position', { index: currentIndex + 1, length: queue.length }) }}
</span> </span>
</button> </button>

View File

@ -65,7 +65,7 @@ onMounted(() => {
}) })
const labels = computed(() => ({ const labels = computed(() => ({
searchPlaceholder: t('components.audio.Search.searchPlaceHolderLabel') searchPlaceholder: t('components.audio.Search.placeholder.search')
})) }))
</script> </script>
@ -73,7 +73,7 @@ const labels = computed(() => ({
<template> <template>
<div> <div>
<h2> <h2>
{{ $t('components.audio.Search.searchHeader') }} {{ $t('components.audio.Search.header.search') }}
</h2> </h2>
<div :class="['ui', {'loading': isLoading }, 'search']"> <div :class="['ui', {'loading': isLoading }, 'search']">
<div class="ui icon big input"> <div class="ui icon big input">
@ -89,7 +89,7 @@ const labels = computed(() => ({
</div> </div>
<template v-if="query.length > 0"> <template v-if="query.length > 0">
<h3 class="ui title"> <h3 class="ui title">
{{ $t('components.audio.Search.artistsHeader') }} {{ $t('components.audio.Search.header.artists') }}
</h3> </h3>
<div v-if="results.artists.length > 0"> <div v-if="results.artists.length > 0">
<div class="ui cards"> <div class="ui cards">
@ -101,12 +101,12 @@ const labels = computed(() => ({
</div> </div>
</div> </div>
<p v-else> <p v-else>
{{ $t('components.audio.Search.noArtistsMessage') }} {{ $t('components.audio.Search.message.noArtists') }}
</p> </p>
</template> </template>
<template v-if="query.length > 0"> <template v-if="query.length > 0">
<h3 class="ui title"> <h3 class="ui title">
{{ $t('components.audio.Search.albumsHeader') }} {{ $t('components.audio.Search.header.albums') }}
</h3> </h3>
<div <div
v-if="results.albums.length > 0" v-if="results.albums.length > 0"
@ -124,7 +124,7 @@ const labels = computed(() => ({
</div> </div>
</div> </div>
<p v-else> <p v-else>
{{ $t('components.audio.Search.noAlbumsMessage') }} {{ $t('components.audio.Search.message.noAlbums') }}
</p> </p>
</template> </template>
</div> </div>

View File

@ -5,334 +5,524 @@
"components": { "components": {
"About": { "About": {
"title": "About", "title": "About",
"funkwhaleHeader": "A social platform to enjoy and share music", "header": {
"funkwhaleDescription": "Funkwhale is a community-driven project that lets you listen and share music and audio within a decentralized, open network.", "funkwhale": "A social platform to enjoy and share music",
"signupHeader": "Sign up", "signup": "Sign up",
"signupDescription": "Sign up now to keep a track of your favorites, create playlists, discover new content and much more!", "publicContent": "Browse public content",
"quotaDescription": "Users on this pod also get {quota} of free storage to upload their own content!", "findApp": "Find an app",
"registrationsClosedHelp": "Registrations are closed on this pod. You can signup on another pod using the link below.", "aboutPod": "About this pod"
"findOtherPod": "Find another pod", },
"alreadyLoggedIn": "You're already signed in!", "description": {
"greetingMessage": "Hello {username}", "funkwhale": "Funkwhale is a community-driven project that lets you listen and share music and audio within a decentralized, open network.",
"aboutPodHeader": "About this pod", "signup": "Sign up now to keep a track of your favorites, create playlists, discover new content and much more!",
"noDescription": "No description available", "quota": "Users on this pod also get {quota} of free storage to upload their own content!",
"activeUsers": "{users} active user | {users} active users", "publicContent": "Listen to public albums and playlists shared on this pod.",
"hoursOfMusic": "{hours} hour of music | {hours} hours of music", "findApp": "Use Funkwhale on other devices with our apps."
"learnMoreLink": "Learn More", },
"publicContentHeader": "Browse public content", "placeholder": {
"publicContentDescription": "Listen to public albums and playlists shared on this pod.", "noDescription": "No description available"
"findAppHeader": "Find an app", },
"findAppDescription": "Use Funkwhale on other devices with our apps." "message": {
"greeting": "Hello {username}",
"loggedIn": "You're already signed in!"
},
"link": {
"learnMore": "Learn more",
"findOtherPod": "Find another pod"
},
"stat": {
"activeUsers": "{users} active user | {users} active users",
"hoursOfMusic": "{hours} hour of music | {hours} hours of music"
},
"help": {
"closedRegistrations": "Registrations are closed on this pod. You can signup on another pod using the link below."
}
}, },
"AboutPod": { "AboutPod": {
"title": "About", "title": "About",
"aboutPod": "About this pod",
"rules": "Rules",
"termsAndPrivacy": "Terms and privacy policy",
"features": "Features",
"statistics": "Statistics",
"noDescription": "No description available",
"noRules": "No rules available",
"noTerms": "No terms available",
"funkwhaleVersion": "Funkwhale version",
"notApplicable": "N/A", "notApplicable": "N/A",
"federation": "Federation", "header": {
"enabled": "Enabled", "about":"About this pod",
"disabled": "Disabled", "rules": "Rules",
"allowList": "Allow-list", "terms": "Terms and privacy policy",
"anonymousAccess": "Anonymous access", "features": "Features",
"registrations": "Registrations", "contact": "Contact",
"open": "Open", "statistics": "Statistics"
"closed": "Closed", },
"uploadQuota": "Upload quota", "placeholder": {
"activeUsers": "{users} active user | {users} active users", "noDescription": "No description available",
"hoursOfMusic": "{hours} hour of music | {hours} hours of music", "noRules": "No rules available",
"artistsCount": "{artists} artist | {artists} artists", "noTerms": "No terms available"
"albumsCount": "{albums} album | {albums} albums", },
"tracksCount": "{tracks} track | {tracks} tracks", "message": {
"listeningsCount": "{listenings} listening | {listenings} listenings", "contact": "Send us an email: {contactEmail}"
"contactHeader": "Contact", },
"contactEmail": "Send us an email: {contactEmail}", "link": {
"introductionLink": "Introdution" "about": "About this pod",
"rules": "Rules",
"terms": "Terms and privacy policy",
"features": "Features",
"statistics": "Statistics",
"introduction": "Introduction"
},
"feature": {
"version": "Funkwhale version",
"federation": "Federation",
"allowList": "Allow-list",
"anonymousAccess": "Anonymous access",
"registrations": "Registrations",
"quota": "Upload quota",
"status": {
"enabled": "Enabled",
"disabled": "Disabled",
"open": "Open",
"closed": "Closed"
}
},
"stat": {
"activeUsers": "{users} active user | {users} active users",
"hoursOfMusic": "{hours} hour of music | {hours} hours of music",
"artistsCount": "{artists} artist | {artists} artists",
"albumsCount": "{albums} album | {albums} albums",
"tracksCount": "{tracks} track | {tracks} tracks",
"listeningsCount": "{listenings} listening | {listenings} listenings"
}
}, },
"Home": { "Home": {
"title": "Home", "title": "Home",
"welcomeMessage": "Welcome to {podName}!", "header": {
"aboutPod": "About this Funkwhale pod", "welcome": "Welcome to {podName}!",
"noDescription": "No description available", "about":"About this Funkwhale pod",
"learnMore": "Learn more", "statistics": "Statistics",
"serverRules": "Server rules", "contact": "Contact",
"statistics": "Statistics", "aboutFunkwhale": "About Funkwhale",
"activeUsers": "{users} active user | {users} active users", "login": "Log in",
"hoursOfMusic": "{hours} hour of music | {hours} hours of music", "signup": "Sign up",
"contactHeader": "Contact", "links": "Useful links",
"aboutFunkwhale": "About Funkwhale", "newAlbums": "Recently added albums",
"funkwhaleDescription": "This pod runs Funkwhale, a community-driven project that lets you listen and share music and audio within a decentralized, open network.", "newChannels": "New channels"
"funkwhaleAddendum": "Funkwhale is free and developed by a friendly community of volunteers.", },
"websiteLink": "Visit funkwhale.audio", "description": {
"loginHeader": "Log In", "signup": "Sign up now to keep a track of your favorites, create playlists, discover new content and much more!",
"signupHeader": "Sign up", "quota": "Users on this pod also get {quota} of free storage to upload their own content!",
"signupDescription": "Sign up now to keep a track of your favorites, create playlists, discover new content and much more!", "funkwhale": {
"uploadQuota": "Users on this pod also get {quota} of free storage to upload their own content!", "paragraph1": "This pod runs Funkwhale, a community-driven project that lets you listen and share music and audio within a decentralized, open network.",
"registrationsClosed": "Registrations are closed on this pod. You can signup on another pod using the link below.", "paragraph2": "Funkwhale is free and developed by a friendly community of volunteers."
"findOtherPod": "Find another pod", }
"usefulLinks": "Useful links", },
"browsePublicContent": "Browse public content", "placeholder": {
"publicContentDescription": "Listen to public albums and playlists shared on this pod.", "noDescription": "No description available"
"mobileApps": "Mobile apps", },
"mobileAppsDescription": "Use Funkwhale on other devices with our apps", "link": {
"userGuides": "User guides", "learnMore": "Learn more",
"userGuidesDescription": "Discover everything you need to know about Funkwhale and its features", "rules": "Server rules",
"recentlyAddedLabel": "Recently added albums", "funkwhale": "Visit funkwhale.audio",
"viewMore": "View more…", "findOtherPod": "Find another pod",
"newChannelsLabel": "New channels" "viewMore": "View more…",
"publicContent": {
"label": "Browse public content",
"description": "Listen to public albums and playlists shared on this pod."
},
"mobileApps": {
"label": "Mobile apps",
"description": "Use Funkwhale on other devices with our apps"
},
"userGuides": {
"label": "User guides",
"description": "Discover everything you need to know about Funkwhale and its features"
}
},
"stat": {
"activeUsers": "{users} active user | {users} active users",
"hoursOfMusic": "{hours} hour of music | {hours} hours of music"
},
"help": {
"registrationsClosed": "Registrations are closed on this pod. You can signup on another pod using the link below."
}
}, },
"PageNotFound": { "PageNotFound": {
"title": "Page not found", "title": "Page not found",
"pageNotFound": "Page not found!", "header": {
"pageNotFoundMessage": "Sorry, the page you asked for does not exist:", "pageNotFound": "Page not found!"
"homeLink": "Go to home page" },
"message": {
"pageNotFound": "Sorry, the page you asked for does not exist:"
},
"link": {
"home": "Go to home page"
}
}, },
"Queue": { "Queue": {
"queue": "Queue", "label": {
"duration": "Duration", "queue": "Queue",
"addArtistContentFilter": "Hide content from this artist…", "duration": "Duration",
"restart": "Restart track", "addArtistContentFilter": "Hide content from this artist…",
"previous": "Previous track", "restart": "Restart track",
"next": "Next track", "previous": "Previous track",
"pause": "Pause", "next": "Next track",
"play": "Play", "pause": "Pause",
"remove": "Remove", "play": "Play",
"selectTrack": "Select track", "remove": "Remove",
"favorite": "Favorite track", "selectTrack": "Select track",
"trackLoadFailure": "The track cannot be loaded", "favorite": "Favorite track"
"automaticPlay": "The next track will play automatically in a few seconds…", },
"connectivityWarning": "You may have a connectivity issue.", "header": {
"closeButton": "Close", "failure": "The track cannot be loaded",
"clearButton": "Clear", "radio": "You have a radio playing"
"queuePosition":"Track {index} of {length}", },
"radioPlaying": "You have a radio playing", "message": {
"appendTracks": "New tracks will be appended here automatically.", "automaticPlay": "The next track will play automatically in a few seconds…",
"stopRadio": "Stop radio" "radio": "New tracks will be appended here automatically."
},
"warning": {
"connectivity": "You may have a connectivity issue."
},
"button": {
"close": "Close",
"clear": "Clear",
"stopRadio": "Stop radio"
},
"display": {
"queuePosition":"Track {index} of {length}"
}
}, },
"RemoteSearchForm": { "RemoteSearchForm": {
"subscribeRss": "Subscribe to a podcast RSS feed", "label": {
"subscribeFediverse": "Subscribe to a podcast hosted on the Fediverse", "rss": {
"rssLocation": "RSS feed location", "title": "Subscribe to a podcast RSS feed",
"fediverseObject": "Fediverse object", "fieldLabel": "RSS feed location",
"rssPlaceholder": "https://website.example.com/rss.xml", "fieldPlaceholder": "https://website.example.com/rss.xml"
"fediversePlaceholder": "@username@example.com", },
"fetchFailureMessage": "This object cannot be retrieved", "fediverse": {
"rss": "RSS", "title": "Fediverse object",
"fediverse": "Fediverse", "fieldLabel": "Fediverse object",
"objectFetchError": "Error while fetching object", "fieldPlaceholder": "@username@example.com"
"rssDescription": "Use this form to subscribe to an RSS feed from its URL.", }
"fediverseDescription": "Use this form to subscribe to a channel hosted somewhere else on the Fediverse.", },
"searchButton": "Search", "header": {
"unsupportedObject": "This kind of object isn't supported yet" "fetchFailed": "Error while fetching object"
},
"description": {
"rss": "Use this form to subscribe to an RSS feed from its URL.",
"fediverse": "Use this form to subscribe to a channel hosted somewhere else on the Fediverse."
},
"button": {
"search": "Search",
"rss": "RSS",
"fediverse": "Fediverse"
},
"error": {
"fetchFailed": "This object cannot be retrieved"
},
"warning": {
"unsupported": "This kind of object isn't supported yet"
}
}, },
"SetInstanceModal": { "SetInstanceModal": {
"currentUrl": "You are now using the Funkwhale instance at {url}", "header": {
"chooseInstance": "Choose your instance", "chooseInstance": "Choose your instance",
"connectionFailure": "It is not possible to connect to the given URL", "failure": "It is not possible to connect to the given URL",
"serverDown": "The server might be down", "suggestions": "Suggested choices"
"notFunkwhaleServer": "The given address is not a Funkwhale server", },
"currentConnection": "You are currently connected to <a href=\"{url}\" target=\"_blank\">{hostName}&nbsp;<i class=\"external icon\" /></a>. If you continue, you will be disconnected from your current instance and all your local data will be deleted.", "message": {
"selectFunkwhalePod": "To continue, please select the Funkwhale instance you want to connect to. Enter the address directly, or select one of the suggested choices.", "newUrl": "You are now using the Funkwhale instance at {url}",
"instanceUrl": "Instance URL", "currentConnection": "You are currently connected to <a href=\"{url}\" target=\"_blank\">{hostName}&nbsp;<i class=\"external icon\" /></a>. If you continue, you will be disconnected from your current instance and all your local data will be deleted."
"submitButton": "Submit", },
"suggestions": "Suggested choices", "help": {
"cancelButton": "Cancel" "serverDown": "The server might be down",
"notFunkwhaleServer": "The given address is not a Funkwhale server",
"selectPod": "To continue, please select the Funkwhale instance you want to connect to. Enter the address directly, or select one of the suggested choices."
},
"button": {
"submit": "Submit",
"cancel": "Cancel"
},
"label": {
"url": "Instance URL"
}
}, },
"ShortcutsModal": { "ShortcutsModal": {
"generalShortcuts": "General shortcuts", "header": {
"showShortcuts": "Show available keyboard shortcuts", "modal": "Keyboard shortcuts"
"focusSearch": "Focus searchbar", },
"unfocusSearch": "Unfocus searchbar", "button": {
"audioShortcuts": "Audio player shortcuts", "close": "Close"
"playPause": "Pause/play the current track", },
"seekBack5": "Seek backwards 5s", "shortcut": {
"seekForward5": "Seek forwards 5s", "general": {
"seekBack30": "Seek backwards 30s", "label": "General shortcuts",
"seekForward30": "Seek forwards 30s", "show": "Show available keyboard shortcuts",
"playPrevious": "Play previous track", "focus": "Focus searchbar",
"playNext":"Play next track", "unfocus": "Unfocus searchbar"
"increaseVolume": "Increase volume", },
"decreaseVolume": "Decrease volume", "audio": {
"toggleMute": "Toggle mute", "label": "Audio player shortcuts",
"expandQueue": "Expand queue/player view", "playPause": "Pause/play the current track",
"toggleLoop": "Toggle queue looping", "seekBack5": "Seek backwards 5s",
"shuffleQueue": "Shuffle queue", "seekForward5": "Seek forwards 5s",
"clearQueue": "Clear queue", "seekBack30": "Seek backwards 30s",
"toggleFavorite": "Toggle favorite", "seekForward30": "Seek forwards 30s",
"modalHeader": "Keyboard shortcuts", "playPrevious": "Play previous track",
"closeButton": "Close" "playNext":"Play next track",
"increaseVolume": "Increase volume",
"decreaseVolume": "Decrease volume",
"toggleMute": "Toggle mute",
"expandQueue": "Expand queue/player view",
"toggleLoop": "Toggle queue looping",
"shuffleQueue": "Shuffle queue",
"clearQueue": "Clear queue",
"toggleFavorite": "Toggle favorite"
}
}
}, },
"Sidebar": { "Sidebar": {
"mainMenu": "Main menu", "label": {
"selectTrack": "Play this track", "main": "Main menu",
"pendingFollows": "Pending follow requests", "play": "Play this track",
"pendingReviewEdits": "Pending review edits", "follows": "Pending follow requests",
"pendingReviewReports": "Pending review reports", "edits": "Pending review edits",
"language": "Language", "reports": "Pending review reports",
"theme": "Theme", "language": "Language",
"addContent": "Add content", "theme": "Theme",
"administration": "Administration", "add": "Add content",
"home": "Home", "administration": "Administration"
"library": "Library", },
"moderation": "Moderation", "header": {
"users": "Users", "main": "Main navigation",
"settings": "Settings", "explore": "Explore",
"login": "Login", "more": "More",
"createAccount": "Create an account", "library": "My library",
"mainNavigation": "Main navigation", "administration": "Administration"
"explore": "Explore", },
"search": "Search", "link": {
"browse": "Browse", "home": "Home",
"podcasts": "Podcasts", "search": "Search",
"albums": "Albums", "browse": "Browse",
"artists": "Artists", "podcasts": "Podcasts",
"playlists": "Playlists", "albums": "Albums",
"radios": "Radios", "artists": "Artists",
"favorites": "Favorites", "playlists": "Playlists",
"channels": "Channels", "radios": "Radios",
"myLibrary": "My library", "favorites": "Favorites",
"more": "More", "channels": "Channels",
"aboutPod": "About this pod", "about": "About this pod",
"switchInstance": "Switch instance" "switchInstance": "Switch instance",
"moderation": "Moderation",
"users": "Users",
"library": "Library",
"settings": "Settings",
"login": "Login",
"createAccount": "Create account"
}
}, },
"admin": { "admin": {
"SettingsGroup": { "SettingsGroup": {
"errorMessage": "Error while saving settings.", "header": {
"successMessage": "Settings updated successfully.", "error": "Error while saving settings.",
"currentImage": "Current image", "image": "Current image"
"saveButton": "Save" },
"message": {
"success": "Settings updated successfully."
},
"button": {
"save": "Save"
}
}, },
"SignupFormBuilder": { "SignupFormBuilder": {
"deleteLabel": "Delete", "label": {
"moveUpLabel": "Move up", "delete": "Delete",
"moveDownLabel": "Move down", "moveUp": "Move up",
"additionalFieldInput": "Additional field", "moveDown": "Move down",
"editForm": "Edit form", "additionalField": "Additional field",
"previewForm": "Preview Form", "helpText": "Help text",
"helpTextLabel": "Help text", "additionalFields": "Additional fields"
"helpTextMessage": "An optional text to be displayed at the start of the sign-up form.", },
"additionalFieldsLabel": "Additional fields", "button": {
"additionalFieldsMessage": "Additional form fields to be displayed in the form. Only shown if manual sign-up validation is enabled.", "edit": "Edit form",
"fieldLabelTableHeader": "Field label", "preview": "Preview Form",
"fieldTypeTableHeader": "Field type", "add": "Add a new field"
"requiredTableHeader": "Required", },
"actionsTableHeader": "Actions", "help": {
"shortTextInput": "Short text", "helpText": "An optional text to be displayed at the start of the sign-up form.",
"longTextInput": "Long text", "additionalFields": "Additional form fields to be displayed in the form. Only shown if manual sign-up validation is enabled."
"requiredTrue": "Yes", },
"requiredFalse": "No", "table": {
"addFieldButton": "Add a new field" "additionalFields": {
"header": {
"label": "Field label",
"type": "Field type",
"required": "Required",
"actions": "Actions"
},
"type": {
"short": "Short text",
"long": "Long text"
},
"required": {
"true": "True",
"false": "False"
}
}
}
} }
}, },
"audio": { "audio": {
"ChannelCard": { "ChannelCard": {
"updatedOn": "Updated on {date}", "title": "Updated on {date}",
"episodeCount": "No episodes | {episode_count} episode | {episode_count} episodes", "meta": {
"trackCount": "No tracks | {tracks_count} track | {tracks_count} tracks" "episodes": "No episodes | {episode_count} episode | {episode_count} episodes",
"tracks": "No tracks | {tracks_count} track | {tracks_count} tracks"
}
}, },
"ChannelEntries": { "ChannelEntries": {
"emptyMessage": "You may need to subscribe to this channel to see its content." "help": {
"subscribe": "You may need to subscribe to this channel to see its content."
}
}, },
"ChannelForm": { "ChannelForm": {
"podcastsLabel": "Podcasts", "label": {
"podcastsHelpText": "Host your episodes and keep your community updated.", "podcast": "Podcasts",
"discographyLabel": "Artist Discography", "discography": "Artist Discography",
"discographyHelpText": "Publish music you make as a nice discography of albums and singles.", "name": "Name",
"namePlaceholder": "Awesome channel name", "username": "Fediverse handle",
"usernamePlaceholder": "awesomechannelname", "image": "Channel Picture",
"errorHeader": "Error while saving channel", "tags": "Tags",
"channelPurposeLegend": "What will this channel be used for?", "language": "Language",
"channelNameLabel": "Name", "description": "Description",
"channelUsernameLabel": "Fediverse handle", "category": "Category",
"channelUsernameDescription": "Used in URLs and to follow this channel in the Fediverse. It cannot be changed later.", "subcategory": "Subcategory",
"channelImageLabel": "Channel Picture", "email": "Owner e-mail address",
"channelTagsLabel": "Tags", "owner": "Owner name"
"channelLanguageLabel": "Language", },
"channelDescriptionLabel": "Description", "help": {
"channelCategoryLabel": "Category", "podcast": "Host your episodes and keep your community updated.",
"channelSubcategoryLabel": "Subcategory", "discography": "Publish music you make as a nice discography of albums and singles.",
"channelEmailLabel": "Owner e-mail address", "username": "Used in URLs and to follow this channel in the Fediverse. It cannot be changed later.",
"channelOwnerLabel": "Owner name", "podcastFields": "Used for the itunes:email and itunes:name field required by certain platforms such as Spotify or iTunes."
"channelPodcastFieldsHelp": "Used for the itunes:email and itunes:name field required by certain platforms such as Spotify or iTunes.", },
"loadingMessage": "Loading" "placeholder": {
"name": "Awesome channel name",
"username": "awesomechannelname"
},
"header": {
"error": "Error while saving channel."
},
"legend": {
"purpose": "What will this channel be used for?"
},
"message": {
"loading": "Loading"
}
}, },
"ChannelSerieCard": { "ChannelSerieCard": {
"episodeCount": "No episodes | {episode_count} episode | {episode_count} episodes" "meta": {
"episodes": "No episodes | {episode_count} episode | {episode_count} episodes"
}
}, },
"ChannelSeries": { "ChannelSeries": {
"showMore": "Show more", "button": {
"emptyMessage": "You may need to subscribe to this channel to see its contents." "showMore": "Show more"
},
"help": {
"subscribe": "You may need to subscribe to this channel to see its contents."
}
}, },
"ChannelsWidget": { "ChannelsWidget": {
"showMore": "Show more" "button": {
"showMore": "Show more"
}
}, },
"EmbedWizard": { "EmbedWizard": {
"anonymousAccessWarning": "Sharing will not work because this pod doesn't allow anonymous users to access content.", "warning": {
"anonymousAccessHelp": "Please contact your admins and ask them to update the corresponding setting.", "anonymous": "Sharing will not work because this pod doesn't allow anonymous users to access content."
"widgetWidthLabel": "Widget width", },
"widgetWidthHelp": "Leave empty for a responsive widget", "help": {
"widgetHeightLabel": "Widget height", "anonymous": "Please contact your admins and ask them to update the corresponding setting.",
"copyButton": "Copy", "embed": "Copy/paste this code in your website HTML",
"embedCodeLabel": "Embed code", "width": "Leave empty for a responsive widget"
"embedCodeHelp": "Copy/paste this code in your website HTML", },
"copyButtonSuccessMessage": "Text copied to clipboard!", "label": {
"previewHeader": "Preview" "width": "Widget width",
"height": "Widget height",
"embed": "Embed code"
},
"button": {
"copy": "Copy"
},
"header": {
"preview": "Preview"
},
"message": {
"copy": "Text copied to clipboard!"
}
}, },
"LibraryFollowButton": { "LibraryFollowButton": {
"unfollowLabel": "Unfollow", "button": {
"cancelLabel": "Cancel follow request", "unfollow": "Unfollow",
"followLabel": "Follow" "cancel": "Cancel follow request",
"follow": "Follow"
}
}, },
"PlayButton": { "PlayButton": {
"playNowLabel": "Play now", "button": {
"addToQueueLabel": "Add to current queue", "playNow": "Play now",
"playNextLabel": "Play next", "addToQueue": "Add to current queue",
"startRadioLabel": "Play similar songs", "playNext": "Play next",
"reportLabel": "Report…", "startRadio": "Play similar songs",
"addToPlaylistLabel": "Add to playlist", "report": "Report…",
"hideArtistLabel": "Hide content from this artist", "addToPlaylist": "Add to playlist",
"playTrackLabel": "Play track", "hideArtist": "Hide content from this artist",
"playAlbumLabel": "Play album", "playTrack": "Play track",
"playArtistLabel": "Play artist", "playAlbum": "Play album",
"playPlaylistLabel": "Play playlist", "playArtist": "Play artist",
"playTracksLabel": "Play tracks", "playPlaylist": "Play playlist",
"moreTitle": "More…", "playTracks": "Play tracks",
"notAvailableTitle": "This track is not available in any library you have access to", "episodeDetails": "Episode details",
"episodeDetailsButton": "Episode details", "trackDetails": "Track details",
"trackDetailsButton": "Track details", "discretePlay": "Play"
"discretePlayButton": "Play" },
"title": {
"more": "More…",
"unavailable": "This track is not available in any library you have access to"
}
}, },
"Player": { "Player": {
"audioPlayerLabel": "Media player", "label": {
"previousTrackLabel": "Previous track", "audioPlayer": "Media player",
"playLabel": "Play", "previousTrack": "Previous track",
"pauseLabel": "Pause", "play": "Play",
"nextTrackLabel": "Next track", "pause": "Pause",
"unmuteLabel": "Unmute", "nextTrack": "Next track",
"muteLabel": "Mute", "unmute": "Unmute",
"expandQueueLabel": "Expand queue", "mute": "Mute",
"loopingDisabledLabel": "Looping disabled. Click to switch to single-track looping.", "expandQueue": "Expand queue",
"loopingSingleLabel": "Looping on a single track. Click to switch to whole queue looping.", "loopingDisabled": "Looping disabled. Click to switch to single-track looping.",
"loopingWholeQueueLabel": "Looping on whole queue. Click to disable looping.", "loopingSingle": "Looping on a single track. Click to switch to whole queue looping.",
"shuffleQueueLabel": "Shuffle your queue", "loopingWholeQueue": "Looping on whole queue. Click to disable looping.",
"clearQueueLabel": "Clear your queue", "shuffleQueue": "Shuffle your queue",
"addArtistContentFilterLabel": "Hide content from this artist…", "clearQueue": "Clear your queue",
"playerHeader": "Audio player and controls", "addArtistContentFilter": "Hide content from this artist…"
"queuePosition": "{index} of {length}" },
"header": {
"player": "Audio player and controls"
},
"meta": {
"position": "{index} of {length}"
}
}, },
"Search": { "Search": {
"searchPlaceHolderLabel": "Artist, album, track…", "header": {
"searchHeader": "Search for some music", "search": "Search for some music",
"artistsHeader": "Artists", "artists": "Artists",
"albumsHeader": "Albums", "albums": "Albums"
"noArtistsMessage": "No artist matched your query", },
"noAlbumsMessage": "No album matched your query" "message": {
"noArtists": "No artist matched your query",
"noAlbums": "No album matched your query"
},
"placeholder": {
"search": "Artist, album, track…"
}
}, },
"SearchBar": { "SearchBar": {
"placeHolderLabel": "Search for artists, albums, tracks…", "placeHolderLabel": "Search for artists, albums, tracks…",