diff --git a/front/src/App.vue b/front/src/App.vue index bf9a1e26108750e7d5f2609f0c65e9ecdfdc81fc..e8cac74761c84e5d26ea354fb400b61f3543e0f4 100644 --- a/front/src/App.vue +++ b/front/src/App.vue @@ -7,22 +7,25 @@ <div class="ui container"> <div class="ui stackable equal height stackable grid"> <div class="three wide column"> - <h4 class="ui header">Links</h4> + <i18next tag="h4" class="ui header" path="Links"></i18next> <div class="ui link list"> - <p>{{ $t('Hello, world!') }}</p> <router-link class="item" to="/about"> - About this instance + <i18next path="About this instance" /> </router-link> - <a href="https://funkwhale.audio" class="item" target="_blank">Official website</a> - <a href="https://docs.funkwhale.audio" class="item" target="_blank">Documentation</a> - <a href="https://code.eliotberriot.com/funkwhale/funkwhale" class="item" target="_blank">Source code</a> - <a href="https://code.eliotberriot.com/funkwhale/funkwhale/issues" class="item" target="_blank">Issue tracker</a> + <i18next tag="a" href="https://funkwhale.audio" class="item" target="_blank" path="Official website" /> + <i18next tag="a" href="https://docs.funkwhale.audio" class="item" target="_blank" path="Documentation" /> + <i18next tag="a" href="https://code.eliotberriot.com/funkwhale/funkwhale" class="item" target="_blank" path="Source code" /> + <i18next tag="a" href="https://code.eliotberriot.com/funkwhale/funkwhale/issues" class="item" target="_blank" path="Issue tracker" /> </div> </div> <div class="ten wide column"> - <h4 class="ui header">About funkwhale</h4> - <p>Funkwhale is a free and open-source project run by volunteers. You can help us improve the platform by reporting bugs, suggesting features and share the project with your friends!</p> - <p>The funkwhale logo was kindly designed and provided by Francis Gading.</p> + <i18next tag="h4" class="ui header" path="About funkwhale" /> + <p> + <i18next path="Funkwhale is a free and open-source project run by volunteers. You can help us improve the platform by reporting bugs, suggesting features and share the project with your friends!"/> + </p> + <p> + <i18next path="The funkwhale logo was kindly designed and provided by Francis Gading."/> + </p> </div> </div> </div> @@ -32,7 +35,6 @@ :dsn="$store.state.instance.settings.raven.front_dsn.value"> </raven> <playlist-modal v-if="$store.state.auth.authenticated"></playlist-modal> - </div> </template> @@ -50,8 +52,6 @@ export default { PlaylistModal }, created () { - // this.$i18n.i18next.changeLanguage('fr') - console.log(this.$t('Hello, world!')) this.$store.dispatch('instance/fetchSettings') let self = this setInterval(() => { diff --git a/front/src/components/activity/Like.vue b/front/src/components/activity/Like.vue index ffb8312787fa366490e0172a0f71dcdbffbfc77d..deda121cc9f8def680eeebd08159fc92c5ee97db 100644 --- a/front/src/components/activity/Like.vue +++ b/front/src/components/activity/Like.vue @@ -5,17 +5,20 @@ </div> <div class="content"> <div class="summary"> - <slot name="user"></slot> - favorited a track - <slot name="date"></slot> + <i18next path="{%0%} favorited a track {%1%}"> + <slot name="user"></slot> + <slot name="date"></slot> + </i18next> </div> <div class="extra text"> <router-link :to="{name: 'library.tracks.detail', params: {id: event.object.local_id }}">{{ event.object.name }}</router-link> - <template v-if="event.object.album">from album {{ event.object.album }}, by <em>{{ event.object.artist }}</em> - </template> - <template v-else>, by <em>{{ event.object.artist }}</em> - </template> - + <i18next path="from album {%0%}, by {%1%}" v-if="event.object.album"> + {{ event.object.album }} + <em>{{ event.object.artist }}</em> + </i18next> + <i18next path=", by {%0%}" v-else> + <em>{{ event.object.artist }}</em> + </i18next> </div> </div> </div> diff --git a/front/src/components/activity/Listen.vue b/front/src/components/activity/Listen.vue index 7c8ee8a69e30666b7fc09e1264e75e6b49ade867..d207c280deef14f44cada9342a2732eabfdc1c48 100644 --- a/front/src/components/activity/Listen.vue +++ b/front/src/components/activity/Listen.vue @@ -5,17 +5,20 @@ </div> <div class="content"> <div class="summary"> - <slot name="user"></slot> - listened to a track - <slot name="date"></slot> + <i18next path="{%0%} listened to a track {%1%}"> + <slot name="user"></slot> + <slot name="date"></slot> + </i18next> </div> <div class="extra text"> <router-link :to="{name: 'library.tracks.detail', params: {id: event.object.local_id }}">{{ event.object.name }}</router-link> - <template v-if="event.object.album">from album {{ event.object.album }}, by <em>{{ event.object.artist }}</em> - </template> - <template v-else>, by <em>{{ event.object.artist }}</em> - </template> - + <i18next path="from album {%0%}, by {%1%}" v-if="event.object.album"> + {{ event.object.album }} + <em>{{ event.object.artist }}</em> + </i18next> + <i18next path=", by {%0%}" v-else> + <em>{{ event.object.artist }}</em> + </i18next> </div> </div> </div> diff --git a/front/src/components/audio/PlayButton.vue b/front/src/components/audio/PlayButton.vue index f2a3898622c09852eb6e05b77c549a76bbf9a6ee..14d381ca19517efa6641e047fc94cd6aed4f1795 100644 --- a/front/src/components/audio/PlayButton.vue +++ b/front/src/components/audio/PlayButton.vue @@ -1,18 +1,18 @@ <template> <div :class="['ui', {'tiny': discrete}, 'buttons']"> <button - title="Add to current queue" + :title="$t('Add to current queue')" @click="add" :class="['ui', {loading: isLoading}, {'mini': discrete}, {disabled: !playable}, 'button']"> <i class="ui play icon"></i> - <template v-if="!discrete"><slot>Play</slot></template> + <template v-if="!discrete"><slot><i18next path="Play"/></slot></template> </button> <div v-if="!discrete" :class="['ui', {disabled: !playable}, 'floating', 'dropdown', 'icon', 'button']"> <i class="dropdown icon"></i> <div class="menu"> - <div class="item"@click="add"><i class="plus icon"></i> Add to queue</div> - <div class="item"@click="addNext()"><i class="step forward icon"></i> Play next</div> - <div class="item"@click="addNext(true)"><i class="arrow down icon"></i> Play now</div> + <div class="item"@click="add"><i class="plus icon"></i><i18next path="Add to queue"/></div> + <div class="item"@click="addNext()"><i class="step forward icon"></i><i18next path="Play next"/></div> + <div class="item"@click="addNext(true)"><i class="arrow down icon"></i><i18next path="Play now"/></div> </div> </div> </div> diff --git a/front/src/components/audio/Player.vue b/front/src/components/audio/Player.vue index 31f6dc35ac3478a9b3c84b15a76ea9adcc044882..ad90a599528a09cfd287389ddfe22a7585f9fa69 100644 --- a/front/src/components/audio/Player.vue +++ b/front/src/components/audio/Player.vue @@ -57,44 +57,44 @@ <div class="two wide column controls ui grid"> <div - title="Previous track" + :title="$t('Previous track')" class="two wide column control" :disabled="emptyQueue"> <i @click="previous" :class="['ui', 'backward', {'disabled': emptyQueue}, 'big', 'icon']"></i> </div> <div v-if="!playing" - title="Play track" + :title="$t('Play track')" class="two wide column control"> <i @click="togglePlay" :class="['ui', 'play', {'disabled': !currentTrack}, 'big', 'icon']"></i> </div> <div v-else - title="Pause track" + :title="$t('Pause track')" class="two wide column control"> <i @click="togglePlay" :class="['ui', 'pause', {'disabled': !currentTrack}, 'big', 'icon']"></i> </div> <div - title="Next track" + :title="$t('Next track')" class="two wide column control" :disabled="!hasNext"> <i @click="next" :class="['ui', {'disabled': !hasNext}, 'step', 'forward', 'big', 'icon']" ></i> </div> <div class="two wide column control volume-control"> - <i title="Unmute" @click="$store.commit('player/volume', 1)" v-if="volume === 0" class="volume off secondary icon"></i> - <i title="Mute" @click="$store.commit('player/volume', 0)" v-else-if="volume < 0.5" class="volume down secondary icon"></i> - <i title="Mute" @click="$store.commit('player/volume', 0)" v-else class="volume up secondary icon"></i> + <i :title="$t('Unmute')" @click="$store.commit('player/volume', 1)" v-if="volume === 0" class="volume off secondary icon"></i> + <i :title="$t('Mute')" @click="$store.commit('player/volume', 0)" v-else-if="volume < 0.5" class="volume down secondary icon"></i> + <i :title="$t('Mute')" @click="$store.commit('player/volume', 0)" v-else class="volume up secondary icon"></i> <input type="range" step="0.05" min="0" max="1" v-model="sliderVolume" /> </div> <div class="two wide column control looping"> <i - title="Looping disabled. Click to switch to single-track looping." + :title="$t('Looping disabled. Click to switch to single-track looping.')" v-if="looping === 0" @click="$store.commit('player/looping', 1)" :disabled="!currentTrack" :class="['ui', {'disabled': !currentTrack}, 'step', 'repeat', 'secondary', 'icon']"></i> <i - title="Looping on a single track. Click to switch to whole queue looping." + :title="$t('Looping on a single track. Click to switch to whole queue looping.')" v-if="looping === 1" @click="$store.commit('player/looping', 2)" :disabled="!currentTrack" @@ -102,7 +102,7 @@ <span class="ui circular tiny orange label">1</span> </i> <i - title="Looping on whole queue. Click to disable looping." + :title="$t('Looping on whole queue. Click to disable looping.')" v-if="looping === 2" @click="$store.commit('player/looping', 0)" :disabled="!currentTrack" @@ -111,14 +111,14 @@ </div> <div :disabled="queue.tracks.length === 0" - title="Shuffle your queue" + :title="$t('Shuffle your queue')" class="two wide column control"> <i @click="shuffle()" :class="['ui', 'random', 'secondary', {'disabled': queue.tracks.length === 0}, 'icon']" ></i> </div> <div class="one wide column"></div> <div :disabled="queue.tracks.length === 0" - title="Clear your queue" + :title="$t('Clear your queue')" class="two wide column control"> <i @click="clean()" :class="['ui', 'trash', 'secondary', {'disabled': queue.tracks.length === 0}, 'icon']" ></i> </div> diff --git a/front/src/components/audio/Search.vue b/front/src/components/audio/Search.vue index bb0881862397324f679296ae5cf6dfd93869cea6..890c83f5bfc2d6562eedfda26b9a63a4fe631bf1 100644 --- a/front/src/components/audio/Search.vue +++ b/front/src/components/audio/Search.vue @@ -1,6 +1,6 @@ <template> <div> - <h2>Search for some music</h2> + <h2><i18next path="Search for some music"/></h2> <div :class="['ui', {'loading': isLoading }, 'search']"> <div class="ui icon big input"> <i class="search icon"></i> @@ -8,22 +8,22 @@ </div> </div> <template v-if="query.length > 0"> - <h3 class="ui title">Artists</h3> + <h3 class="ui title"><i18next path="Artists"/></h3> <div v-if="results.artists.length > 0" class="ui stackable three column grid"> <div class="column" :key="artist.id" v-for="artist in results.artists"> <artist-card class="fluid" :artist="artist" ></artist-card> </div> </div> - <p v-else>Sorry, we did not found any artist matching your query</p> + <p v-else><i18next path="Sorry, we did not found any artist matching your query"/></p> </template> <template v-if="query.length > 0"> - <h3 class="ui title">Albums</h3> + <h3 class="ui title"><i18next path="Albums"/></h3> <div v-if="results.albums.length > 0" class="ui stackable three column grid"> <div class="column" :key="album.id" v-for="album in results.albums"> <album-card class="fluid" :album="album" ></album-card> </div> </div> - <p v-else>Sorry, we did not found any album matching your query</p> + <p v-else><i18next path="Sorry, we did not found any album matching your query"/></p> </template> </div> </template> diff --git a/front/src/components/audio/album/Card.vue b/front/src/components/audio/album/Card.vue index bb37b2b2f86635e3324652f4245b08e3fa4a26a9..6742dca4f9b94e88983ad6ec6d4396b11dc14648 100644 --- a/front/src/components/audio/album/Card.vue +++ b/front/src/components/audio/album/Card.vue @@ -10,8 +10,10 @@ </div> <div class="meta"> <span> - By <router-link tag="span" :to="{name: 'library.artists.detail', params: {id: album.artist.id }}"> + <i18next path="By {%0%}"> + <router-link tag="span" :to="{name: 'library.artists.detail', params: {id: album.artist.id }}"> {{ album.artist.name }}</router-link> + </i18next> </span><span class="time" v-if="album.release_date">– {{ album.release_date | year }}</span> </div> <div class="description" v-if="mode === 'rich'"> @@ -36,16 +38,24 @@ </tbody> </table> <div class="center aligned segment" v-if="album.tracks.length > initialTracks"> - <em v-if="!showAllTracks" @click="showAllTracks = true" class="expand">Show {{ album.tracks.length - initialTracks }} more tracks</em> - <em v-else @click="showAllTracks = false" class="expand">Collapse</em> + <em v-if="!showAllTracks" @click="showAllTracks = true" class="expand"> + <i18next path="Show {%0%} more tracks">{{ album.tracks.length - initialTracks }}</i18next> + </em> + <em v-else @click="showAllTracks = false" class="expand"> + <i18next path="Collapse" /> + </em> </div> </div> </div> <div class="extra content"> - <play-button class="mini basic orange right floated" :tracks="album.tracks">Play all</play-button> + <play-button class="mini basic orange right floated" :tracks="album.tracks"> + <i18next path="Play all"/> + </play-button> <span> <i class="music icon"></i> - {{ album.tracks.length }} tracks + <i18next path="{%0%} tracks"> + {{ album.tracks.length }} + </i18next> </span> </div> </div> diff --git a/front/src/components/audio/artist/Card.vue b/front/src/components/audio/artist/Card.vue index a5111434546e43c233d717616aa4363c7e6a36f3..3ad6fb1c60263ac2d350350b3318eecec72885d0 100644 --- a/front/src/components/audio/artist/Card.vue +++ b/front/src/components/audio/artist/Card.vue @@ -27,17 +27,27 @@ </tbody> </table> <div class="center aligned segment" v-if="artist.albums.length > initialAlbums"> - <em v-if="!showAllAlbums" @click="showAllAlbums = true" class="expand">Show {{ artist.albums.length - initialAlbums }} more albums</em> - <em v-else @click="showAllAlbums = false" class="expand">Collapse</em> + <em v-if="!showAllAlbums" @click="showAllAlbums = true" class="expand"> + <i18next path="Show {%0%} more albums"> + {{ artist.albums.length - initialAlbums }} + </i18next> + </em> + <em v-else @click="showAllAlbums = false" class="expand"> + <i18next path="Collapse"/> + </em> </div> </div> </div> <div class="extra content"> <span> <i class="sound icon"></i> - {{ artist.albums.length }} albums + <i18next path="{%0%} albums"> + {{ artist.albums.length }} + </i18next> </span> - <play-button class="mini basic orange right floated" :tracks="allTracks">Play all</play-button> + <play-button class="mini basic orange right floated" :tracks="allTracks"> + <i18next path="Play all"/> + </play-button> </div> </div> </template> diff --git a/front/src/components/audio/track/Table.vue b/front/src/components/audio/track/Table.vue index 512ba1b493d35f71b098d112959a9ac9d3c5e4ef..7045cf9bd222085bbb7fbf1056a24f4c8205cb86 100644 --- a/front/src/components/audio/track/Table.vue +++ b/front/src/components/audio/track/Table.vue @@ -4,9 +4,9 @@ <tr> <th></th> <th></th> - <th colspan="6">Title</th> - <th colspan="6">Artist</th> - <th colspan="6">Album</th> + <i18next tag="th" colspan="6" path="Title"/> + <i18next tag="th" colspan="6" path="Artist"/> + <i18next tag="th" colspan="6" path="Album"/> <th></th> </tr> </thead> @@ -20,20 +20,18 @@ <tfoot class="full-width"> <tr> <th colspan="3"> - <button @click="showDownloadModal = !showDownloadModal" class="ui basic button">Download...</button> + <button @click="showDownloadModal = !showDownloadModal" class="ui basic button"> + <i18next path="Download..."/> + </button> <modal :show.sync="showDownloadModal"> - <div class="header"> - Download tracks - </div> + <i18next tag="div" path="Download tracks" class="header" /> <div class="content"> <div class="description"> - <p>There is currently no way to download directly multiple tracks from funkwhale as a ZIP archive. - However, you can use a command line tools such as <a href="https://curl.haxx.se/" target="_blank">cURL</a> to easily download a list of tracks. - </p> - <p>Simply copy paste the snippet below into a terminal to launch the download.</p> - <div class="ui warning message"> - Keep your PRIVATE_TOKEN secret as it gives access to your account. - </div> + <i18next tag="p" path="There is currently no way to download directly multiple tracks from funkwhale as a ZIP archive. However, you can use a command line tools such as {%0%} to easily download a list of tracks."> + <a href="https://curl.haxx.se/" target="_blank">cURL</a> + </i18next> + <i18next path="Simply copy paste the snippet below into a terminal to launch the download."/> + <i18next tag="div" class="ui warning message" path="Keep your PRIVATE_TOKEN secret as it gives access to your account."/> <pre> export PRIVATE_TOKEN="{{ $store.state.auth.token }}" <template v-for="track in tracks"><template v-if="track.files.length > 0"> @@ -42,9 +40,7 @@ curl -G -o "{{ track.files[0].filename }}" <template v-if="$store.state.auth.aut </div> </div> <div class="actions"> - <div class="ui black deny button"> - Cancel - </div> + <i18next tag="div" class="ui black deny button" path="Cancel" /> </div> </modal> </th> diff --git a/front/src/components/auth/Login.vue b/front/src/components/auth/Login.vue index d232da2a35e38d4f774072fb049473ac5cfa1e86..b06ce89f0da850457c10acaee1d894df98368750 100644 --- a/front/src/components/auth/Login.vue +++ b/front/src/components/auth/Login.vue @@ -2,17 +2,17 @@ <div class="main pusher" v-title="'Log In'"> <div class="ui vertical stripe segment"> <div class="ui small text container"> - <h2>Log in to your Funkwhale account</h2> + <h2><i18next path="Log in to your Funkwhale account"/></h2> <form class="ui form" @submit.prevent="submit()"> <div v-if="error" class="ui negative message"> - <div class="header">We cannot log you in</div> + <div class="header"><i18next path="We cannot log you in"/></div> <ul class="list"> - <li v-if="error == 'invalid_credentials'">Please double-check your username/password couple is correct</li> - <li v-else>An unknown error happend, this can mean the server is down or cannot be reached</li> + <i18next tag="li" v-if="error == 'invalid_credentials'" path="Please double-check your username/password couple is correct"/> + <i18next tag="li" v-else path="An unknown error happend, this can mean the server is down or cannot be reached"/> </ul> </div> <div class="field"> - <label>Username or email</label> + <i18next tag="label" path="Username or email"/> <input ref="username" required @@ -23,7 +23,7 @@ > </div> <div class="field"> - <label>Password</label> + <i18next tag="label" path="Password"/> <input required type="password" @@ -31,9 +31,9 @@ v-model="credentials.password" > </div> - <button :class="['ui', {'loading': isLoading}, 'button']" type="submit">Login</button> + <button :class="['ui', {'loading': isLoading}, 'button']" type="submit"><i18next path="Login"/></button> <router-link class="ui right floated basic button" :to="{path: '/signup'}"> - Create an account + <i18next path="Create an account"/> </router-link> </form> </div> diff --git a/front/src/components/auth/Logout.vue b/front/src/components/auth/Logout.vue index 980740c94cfc415e5afc467186c14d1a193748cc..f5a994e73ff71d96a77fb5bf2fa1b96da8ec7466 100644 --- a/front/src/components/auth/Logout.vue +++ b/front/src/components/auth/Logout.vue @@ -2,9 +2,9 @@ <div class="main pusher" v-title="'Log Out'"> <div class="ui vertical stripe segment"> <div class="ui small text container"> - <h2>Are you sure you want to log out?</h2> - <p>You are currently logged in as {{ $store.state.auth.username }}</p> - <button class="ui button" @click="$store.dispatch('auth/logout')">Yes, log me out!</button> + <h2><i18next path="Are you sure you want to log out?"/></h2> + <i18next tag="p" path="You are currently logged in as {%0%}">{{ $store.state.auth.username }}</i18next> + <button class="ui button" @click="$store.dispatch('auth/logout')"><i18next path="Yes, log me out!"/></button> </form> </div> </div> diff --git a/front/src/components/auth/Profile.vue b/front/src/components/auth/Profile.vue index 9fafccffa83f0e9b63ac6a692de586a4adf9e4f8..ab728c036beb8a29518bb1851a172ff38c1f62d0 100644 --- a/front/src/components/auth/Profile.vue +++ b/front/src/components/auth/Profile.vue @@ -9,16 +9,17 @@ <i class="circular inverted user green icon"></i> <div class="content"> {{ $store.state.auth.profile.username }} - <div class="sub header">Registered since {{ signupDate }}</div> + <i18next class="sub header" path="Registered since {%0%}">{{ signupDate }}</i18next> </div> </h2> - <div class="ui basic green label">this is you!</div> + <div class="ui basic green label"><i18next path="This is you!"/></div> <div v-if="$store.state.auth.profile.is_staff" class="ui yellow label"> <i class="star icon"></i> - Staff member + <i18next path="Staff member"/> </div> <router-link class="ui tiny basic button" :to="{path: '/settings'}"> - <i class="setting icon"> </i>Settings... + <i class="setting icon"> </i> + <i18next path="Settings..."/> </router-link> </div> diff --git a/front/src/components/auth/Settings.vue b/front/src/components/auth/Settings.vue index 859c0d04b97ccecb97911575ad505cdda475ebf5..64f7df714ff9c858ac320d0a707c885c1049a574 100644 --- a/front/src/components/auth/Settings.vue +++ b/front/src/components/auth/Settings.vue @@ -2,13 +2,13 @@ <div class="main pusher" v-title="'Account Settings'"> <div class="ui vertical stripe segment"> <div class="ui small text container"> - <h2 class="ui header">Account settings</h2> + <h2 class="ui header"><i18next path="Account settings"/></h2> <form class="ui form" @submit.prevent="submitSettings()"> <div v-if="settings.success" class="ui positive message"> - <div class="header">Settings updated</div> + <div class="header"><i18next path="Settings updated"/></div> </div> <div v-if="settings.errors.length > 0" class="ui negative message"> - <div class="header">We cannot save your settings</div> + <i18next tag="div" class="header" path="We cannot save your settings"/> <ul class="list"> <li v-for="error in settings.errors">{{ error }}</li> </ul> @@ -20,21 +20,21 @@ <option :value="c.value" v-for="c in f.choices">{{ c.label }}</option> </select> </div> - <button :class="['ui', {'loading': isLoading}, 'button']" type="submit">Update settings</button> + <button :class="['ui', {'loading': isLoading}, 'button']" type="submit"><i18next path="Update settings"/></button> </form> </div> <div class="ui hidden divider"></div> <div class="ui small text container"> - <h2 class="ui header">Change my password</h2> + <h2 class="ui header"><i18next path="Change my password"/></h2> <form class="ui form" @submit.prevent="submitPassword()"> <div v-if="passwordError" class="ui negative message"> - <div class="header">Cannot change your password</div> + <div class="header"><i18next path="Cannot change your password"/></div> <ul class="list"> - <li v-if="passwordError == 'invalid_credentials'">Please double-check your password is correct</li> + <i18next tag="li" v-if="passwordError == 'invalid_credentials'" path="Please double-check your password is correct"/> </ul> </div> <div class="field"> - <label>Old password</label> + <label><i18next path="Old password"/></label> <input required type="password" @@ -43,7 +43,7 @@ v-model="old_password"> </div> <div class="field"> - <label>New password</label> + <label><i18next path="New password"/></label> <input required type="password" @@ -51,7 +51,7 @@ placeholder="Enter your new password" v-model="new_password"> </div> - <button :class="['ui', {'loading': isLoading}, 'button']" type="submit">Change password</button> + <button :class="['ui', {'loading': isLoading}, 'button']" type="submit"><i18next path="Change password"/></button> </form> </div> </div> @@ -80,16 +80,16 @@ export default { 'privacy_level': { type: 'dropdown', initial: this.$store.state.auth.profile.privacy_level, - label: 'Activity visibility', - help: 'Determine the visibility level of your activity', + label: this.$t('Activity visibility'), + help: this.$t('Determine the visibility level of your activity'), choices: [ { value: 'me', - label: 'Nobody except me' + label: this.$t('Nobody except me') }, { value: 'instance', - label: 'Everyone on this instance' + label: this.$t('Everyone on this instance') } ] } diff --git a/front/src/components/auth/Signup.vue b/front/src/components/auth/Signup.vue index 39ca366631367afe452e3dddcaf54f56ad5f511a..57966264f99f0aa732f5ecd306bc6d875f9ca9fc 100644 --- a/front/src/components/auth/Signup.vue +++ b/front/src/components/auth/Signup.vue @@ -2,19 +2,19 @@ <div class="main pusher" v-title="'Sign Up'"> <div class="ui vertical stripe segment"> <div class="ui small text container"> - <h2>Create a funkwhale account</h2> + <h2><i18next path="Create a funkwhale account"/></h2> <form v-if="$store.state.instance.settings.users.registration_enabled.value" :class="['ui', {'loading': isLoadingInstanceSetting}, 'form']" @submit.prevent="submit()"> <div v-if="errors.length > 0" class="ui negative message"> - <div class="header">We cannot create your account</div> + <div class="header"><i18next path="We cannot create your account"/></div> <ul class="list"> <li v-for="error in errors">{{ error }}</li> </ul> </div> <div class="field"> - <label>Username</label> + <i18next tag="label" path="Username"/> <input ref="username" required @@ -24,7 +24,7 @@ v-model="username"> </div> <div class="field"> - <label>Email</label> + <i18next tag="label" path="Email"/> <input ref="email" required @@ -33,7 +33,7 @@ v-model="email"> </div> <div class="field"> - <label>Password</label> + <i18next tag="label" path="Password"/> <div class="ui action input"> <input required @@ -45,9 +45,9 @@ </span> </div> </div> - <button :class="['ui', 'green', {'loading': isLoading}, 'button']" type="submit">Create my account</button> + <button :class="['ui', 'green', {'loading': isLoading}, 'button']" type="submit"><i18next path="Create my account"/></button> </form> - <p v-else>Registration is currently disabled on this instance, please try again later.</p> + <i18next v-else tag="p" path="Registration is currently disabled on this instance, please try again later."/> </div> </div> </div> diff --git a/front/src/components/common/DangerousButton.vue b/front/src/components/common/DangerousButton.vue index 525b4c48ff259babf599b54a2368ad2017c677d3..910209b9dc1c6f506ab759404e3393e484b5b456 100644 --- a/front/src/components/common/DangerousButton.vue +++ b/front/src/components/common/DangerousButton.vue @@ -4,7 +4,7 @@ <modal class="small" :show.sync="showModal"> <div class="header"> - <slot name="modal-header">Do you want to confirm this action?</slot> + <slot name="modal-header"><i18next path="Do you want to confirm this action?"/></slot> </div> <div class="scrolling content"> <div class="description"> @@ -12,9 +12,9 @@ </div> </div> <div class="actions"> - <div class="ui cancel button">Cancel</div> + <div class="ui cancel button"><i18next path="Cancel"/></div> <div :class="['ui', 'confirm', color, 'button']" @click="confirm"> - <slot name="modal-confirm">Confirm</slot> + <slot name="modal-confirm"><i18next path="Confirm"/></slot> </div> </div> </modal> diff --git a/front/src/components/discussion/Comment.vue b/front/src/components/discussion/Comment.vue index a3c5176ecb9b908817b72f62f884c6f87d2b9660..0c0678d86221ea023fa1a319ce541e63b293304f 100644 --- a/front/src/components/discussion/Comment.vue +++ b/front/src/components/discussion/Comment.vue @@ -11,11 +11,13 @@ <span @click="collapsed = false" v-if="truncated && collapsed" - class="expand">Expand</span> - <span + class="expand" + path="Expand"/> + <i18next @click="collapsed = true" v-if="truncated && !collapsed" - class="collapse">Collapse</span> + class="collapse" + path="Collapse"/> </div> </div> </div> diff --git a/front/src/components/favorites/List.vue b/front/src/components/favorites/List.vue index dbef186b6b5c7d8a6aec611b798ab22a41f03362..590d915921c8240867d9b179f1c83490fa631ea3 100644 --- a/front/src/components/favorites/List.vue +++ b/front/src/components/favorites/List.vue @@ -2,11 +2,13 @@ <div class="main pusher" v-title="'Your Favorites'"> <div class="ui vertical center aligned stripe segment"> <div :class="['ui', {'active': isLoading}, 'inverted', 'dimmer']"> - <div class="ui text loader">Loading your favorites...</div> + <div class="ui text loader"><i18next path="Loading your favorites..."/></div> </div> <h2 v-if="results" class="ui center aligned icon header"> <i class="circular inverted heart pink icon"></i> - {{ $store.state.favorites.count }} favorites + <i18next path="{%0%} favorites"> + {{ $store.state.favorites.count }} + </i18next> </h2> <radio-button type="favorites"></radio-button> </div> @@ -14,7 +16,7 @@ <div :class="['ui', {'loading': isLoading}, 'form']"> <div class="fields"> <div class="field"> - <label>Ordering</label> + <i18next tag="label" path="Ordering"/> <select class="ui dropdown" v-model="ordering"> <option v-for="option in orderingOptions" :value="option[0]"> {{ option[1] }} @@ -22,14 +24,14 @@ </select> </div> <div class="field"> - <label>Ordering direction</label> + <i18next tag="label" path="Ordering direction"/> <select class="ui dropdown" v-model="orderingDirection"> - <option value="">Ascending</option> - <option value="-">Descending</option> + <option value=""><i18next path="Ascending"/></option> + <option value="-"><i18next path="Descending"/></option> </select> </div> <div class="field"> - <label>Results per page</label> + <i18next tag="label" path="Results per page"/> <select class="ui dropdown" v-model="paginateBy"> <option :value="parseInt(12)">12</option> <option :value="parseInt(25)">25</option> @@ -83,9 +85,9 @@ export default { orderingDirection: defaultOrdering.direction, ordering: defaultOrdering.field, orderingOptions: [ - ['title', 'Track name'], - ['album__title', 'Album name'], - ['artist__name', 'Artist name'] + ['title', this.$t('Track name')], + ['album__title', this.$t('Album name')], + ['artist__name', this.$t('Artist name')] ] } }, diff --git a/front/src/components/favorites/TrackFavoriteIcon.vue b/front/src/components/favorites/TrackFavoriteIcon.vue index d4838ba5f336ff0375145ed5925029a19bf68587..d8d62afaaa363e520c45e600d18a18fded34cf1d 100644 --- a/front/src/components/favorites/TrackFavoriteIcon.vue +++ b/front/src/components/favorites/TrackFavoriteIcon.vue @@ -1,12 +1,8 @@ <template> <button @click="$store.dispatch('favorites/toggle', track.id)" v-if="button" :class="['ui', 'pink', {'inverted': isFavorite}, {'favorited': isFavorite}, 'button']"> <i class="heart icon"></i> - <template v-if="isFavorite"> - In favorites - </template> - <template v-else> - Add to favorites - </template> + <i18next v-if="isFavorite" path="In favorites"/> + <i18next v-else path="Add to favorites"/> </button> <i v-else @click="$store.dispatch('favorites/toggle', track.id)" :class="['favorite-icon', 'heart', {'pink': isFavorite}, {'favorited': isFavorite}, 'link', 'icon']" :title="title"></i> </template> @@ -20,9 +16,9 @@ export default { computed: { title () { if (this.isFavorite) { - return 'Remove from favorites' + return this.$t('Remove from favorites') } else { - return 'Add to favorites' + return this.$t('Add to favorites') } }, isFavorite () { diff --git a/front/src/components/instance/Stats.vue b/front/src/components/instance/Stats.vue index 884809f3a247515d5f2aebcc5d40ab6b14646d15..7da9fc6ede056c4174f5dc6004f5c6233664008b 100644 --- a/front/src/components/instance/Stats.vue +++ b/front/src/components/instance/Stats.vue @@ -2,32 +2,26 @@ <div> <div v-if="stats" class="ui stackable two column grid"> <div class="column"> - <h3 class="ui left aligned header">User activity</h3> + <h3 class="ui left aligned header"><i18next path="User activity"/></h3> <div class="ui mini horizontal statistics"> <div class="statistic"> <div class="value"> <i class="green user icon"></i> {{ stats.users }} </div> - <div class="label"> - Users - </div> + <i18next tag="div" class="label" path="users"/> </div> <div class="statistic"> <div class="value"> <i class="orange sound icon"></i> {{ stats.listenings }} </div> - <div class="label"> - tracks listened - </div> + <i18next tag="div" class="label" path="tracks listened"/> </div> <div class="statistic"> <div class="value"> <i class="pink heart icon"></i> {{ stats.track_favorites }} </div> - <div class="label"> - Tracks favorited - </div> + <i18next tag="div" class="label" path="Tracks favorited"/> </div> </div> </div> @@ -38,33 +32,25 @@ <div class="value"> {{ parseInt(stats.music_duration) }} </div> - <div class="label"> - hours of music - </div> + <i18next tag="div" class="label" path="hours of music"/> </div> <div class="statistic"> <div class="value"> {{ stats.artists }} </div> - <div class="label"> - Artists - </div> + <i18next tag="div" class="label" path="Artists"/> </div> <div class="statistic"> <div class="value"> {{ stats.albums }} </div> - <div class="label"> - Albums - </div> + <i18next tag="div" class="label" path="Albums"/> </div> <div class="statistic"> <div class="value"> {{ stats.tracks }} </div> - <div class="label"> - tracks - </div> + <i18next tag="div" class="label" path="tracks"/> </div> </div> </div> diff --git a/front/src/components/library/import/ArtistImport.vue b/front/src/components/library/import/ArtistImport.vue index fb531439b4eb06c1afb1aab9be605ec5bc6219d6..7486a65dafa4a3381a32b9ef465f2294b9247aec 100644 --- a/front/src/components/library/import/ArtistImport.vue +++ b/front/src/components/library/import/ArtistImport.vue @@ -4,7 +4,7 @@ <a :href="getMusicbrainzUrl('artist', metadata.id)" target="_blank" title="View on MusicBrainz">{{ metadata.name }}</a> </h3> <form class="ui form" @submit.prevent=""> - <h6 class="ui header">Filter album types</h6> + <h6 class="ui header"><i18next path="Filter album types"/></h6> <div class="inline fields"> <div class="field" v-for="t in availableReleaseTypes"> <div class="ui checkbox"> @@ -13,7 +13,7 @@ </div> </div> <div class="field"> - <label>Query template</label> + <i18next tag="label" path="Query template"/> <input v-model="customQueryTemplate" /> </div> </div> @@ -53,8 +53,8 @@ export default Vue.extend({ releaseImportData: [], releaseGroupsData: {}, releases: [], - releaseTypes: ['Album'], - availableReleaseTypes: ['Album', 'Live', 'Compilation', 'EP', 'Single', 'Other'] + releaseTypes: [this.$t('Album')], + availableReleaseTypes: [this.$t('Album'), this.$t('Live'), this.$t('Compilation'), this.$t('EP'), this.$t('Single'), this.$t('Other')] } }, created () { diff --git a/front/src/components/library/import/BatchDetail.vue b/front/src/components/library/import/BatchDetail.vue index 362a5acd17972e6b26bc3deca8ae5881b2865e79..c7894fcc0249c4f27f58e6c6f29327b52f3929f5 100644 --- a/front/src/components/library/import/BatchDetail.vue +++ b/front/src/components/library/import/BatchDetail.vue @@ -20,11 +20,11 @@ <table class="ui unstackable table"> <thead> <tr> - <th>Job ID</th> - <th>Recording MusicBrainz ID</th> - <th>Source</th> - <th>Status</th> - <th>Track</th> + <i18next tag="th" path="Job ID"/> + <i18next tag="th" path="Recording MusicBrainz ID"/> + <i18next tag="th" path="Source"/> + <i18next tag="th" path="Status"/> + <i18next tag="th" path="Track"/> </tr> </thead> <tbody> diff --git a/front/src/components/library/import/BatchList.vue b/front/src/components/library/import/BatchList.vue index 857fef0457256aa7e7ea12f7d355bab1a36b32fe..324c3990a1494892435162bb52aa78fb516478c1 100644 --- a/front/src/components/library/import/BatchList.vue +++ b/front/src/components/library/import/BatchList.vue @@ -5,20 +5,20 @@ <button class="ui left floated labeled icon button" @click="fetchData(previousLink)" - :disabled="!previousLink"><i class="left arrow icon"></i> Previous</button> + :disabled="!previousLink"><i class="left arrow icon"></i><i18next path="Previous"/></button> <button class="ui right floated right labeled icon button" @click="fetchData(nextLink)" - :disabled="!nextLink">Next <i class="right arrow icon"></i></button> + :disabled="!nextLink"><i18next path="Next"/><i class="right arrow icon"></i></button> <div class="ui hidden clearing divider"></div> <div class="ui hidden clearing divider"></div> <table v-if="results.length > 0" class="ui unstackable table"> <thead> <tr> - <th>ID</th> - <th>Launch date</th> - <th>Jobs</th> - <th>Status</th> + <i18next tag="th" path="ID"/> + <i18next tag="th" path="Launch date"/> + <i18next tag="th" path="Jobs"/> + <i18next tag="th" path="Status"/> </tr> </thead> <tbody> diff --git a/front/src/components/library/import/FileUpload.vue b/front/src/components/library/import/FileUpload.vue index 35338c656170f3329a024d18f390916f74d81355..9a4b820e3fddac7a624999e49b64ed91ed84f777 100644 --- a/front/src/components/library/import/FileUpload.vue +++ b/front/src/components/library/import/FileUpload.vue @@ -17,29 +17,31 @@ @input-file="inputFile" ref="upload"> <i class="upload icon"></i> - Select files to upload... + <i18next path="Select files to upload..."/> </file-upload-widget> <button :class="['ui', 'right', 'floated', 'icon', {disabled: files.length === 0}, 'button']" v-if="!$refs.upload || !$refs.upload.active" @click.prevent="$refs.upload.active = true"> <i class="play icon" aria-hidden="true"></i> - Start Upload + <i18next path="Start Upload"/> </button> <button type="button" class="ui right floated icon yellow button" v-else @click.prevent="$refs.upload.active = false"> <i class="pause icon" aria-hidden="true"></i> - Stop Upload + <i18next path="Stop Upload"/> </button> </div> <div class="ui hidden clearing divider"></div> - <p v-if="batch"> - Once all your files are uploaded, simply head over <router-link :to="{name: 'library.import.batches.detail', params: {id: batch.id }}">import detail page</router-link> to check the import status. - </p> + <i18next v-if="batch" path="Once all your files are uploaded, simply head over {%0%} to check the import status."> + <router-link :to="{name: 'library.import.batches.detail', params: {id: batch.id }}"> + <i18next path="import detail page"/> + </router-link> + </i18next> <table class="ui single line table"> <thead> <tr> - <th>File name</th> - <th>Size</th> - <th>Status</th> + <i18next tag="th" path="File name"/> + <i18next tag="th" path="Size"/> + <i18next tag="th" path="Status"/> </tr> </thead> <tbody> @@ -50,10 +52,10 @@ <span v-if="file.error" class="ui red label"> {{ file.error }} </span> - <span v-else-if="file.success" class="ui green label">Success</span> - <span v-else-if="file.active" class="ui yellow label">Uploading...</span> + <i18next v-else-if="file.success" class="ui green label" path="Success"/> + <i18next v-else-if="file.active" class="ui yellow label" path="Uploading..."/> <template v-else> - <span class="ui label">Pending</span> + <i18next class="ui label" path="Pending"/> <button class="ui tiny basic red icon button" @click.prevent="$refs.upload.remove(file)"><i class="delete icon"></i></button> </template> </td> diff --git a/front/src/components/library/import/Main.vue b/front/src/components/library/import/Main.vue index e2b6e484912d803a0494590afa04e6e8931401b8..cf261fad8c3c8eb9b1d47002d9303c33996112ce 100644 --- a/front/src/components/library/import/Main.vue +++ b/front/src/components/library/import/Main.vue @@ -4,45 +4,47 @@ <div class="ui top three attached ordered steps"> <a @click="currentStep = 0" :class="['step', {'active': currentStep === 0}, {'completed': currentStep > 0}]"> <div class="content"> - <div class="title">Import source</div> - <div class="description"> - Uploaded files or external source - </div> + <i18next tag="div" class="title" path="Import source"/> + <i18next tag="div" class="description" path="Uploaded files or external source"/> </div> </a> <a @click="currentStep = 1" :class="['step', {'active': currentStep === 1}, {'completed': currentStep > 1}]"> <div class="content"> - <div class="title">Metadata</div> - <div class="description">Grab corresponding metadata</div> + <i18next tag="div" class="title" path="Metadata"/> + <i18next tag="div" class="description" path="Grab corresponding metadata"/> </div> </a> <a @click="currentStep = 2" :class="['step', {'active': currentStep === 2}, {'completed': currentStep > 2}]"> <div class="content"> - <div class="title">Music</div> - <div class="description">Select relevant sources or files for import</div> + <i18next tag="div" class="title" path="Music"/> + <i18next tag="div" class="description" path="Select relevant sources or files for import"/> </div> </a> </div> <div class="ui hidden divider"></div> <div class="ui centered buttons"> - <button @click="currentStep -= 1" :disabled="currentStep === 0" class="ui icon button"><i class="left arrow icon"></i> Previous step</button> - <button @click="currentStep += 1" v-if="currentStep < 2" class="ui icon button">Next step <i class="right arrow icon"></i></button> + <button @click="currentStep -= 1" :disabled="currentStep === 0" class="ui icon button"><i class="left arrow icon"></i><i18next path="Previous step"/></button> + <button @click="currentStep += 1" v-if="currentStep < 2" class="ui icon button"><i18next path="Next step"/><i class="right arrow icon"></i></button> <button @click="$refs.import.launchImport()" v-if="currentStep === 2" :class="['ui', 'positive', 'icon', {'loading': isImporting}, 'button']" :disabled="isImporting || importData.count === 0" - >Import {{ importData.count }} tracks <i class="check icon"></i></button> + > + <i18next path="Import {%0%} tracks">{{ importData.count }}</i18next> + <i class="check icon"></i> + </button> </div> <div class="ui hidden divider"></div> <div class="ui attached segment"> <template v-if="currentStep === 0"> - <p>First, choose where you want to import the music from :</p> + <i18next tag="p" path="First, choose where you want to import the music from:"/> <form class="ui form"> <div class="field"> <div class="ui radio checkbox"> <input type="radio" id="external" value="external" v-model="currentSource"> - <label for="external">External source. Supported backends: + <label for="external"> + <i18next path="External source. Supported backends:"/> <div v-for="backend in backends" class="ui basic label"> <i v-if="backend.icon" :class="[backend.icon, 'icon']"></i> {{ backend.label }} @@ -53,7 +55,7 @@ <div class="field"> <div class="ui radio checkbox"> <input type="radio" id="upload" value="upload" v-model="currentSource"> - <label for="upload">File upload</label> + <i18next tag="label" for="upload" path="File upload" /> </div> </div> </form> @@ -62,7 +64,7 @@ <div class="column"> <form class="ui form" @submit.prevent=""> <div class="field"> - <label>Search an entity you want to import:</label> + <i18next tag="label" path="Search an entity you want to import:"/> <metadata-search :mb-type="mbType" :mb-id="mbId" @@ -70,29 +72,29 @@ @type-changed="updateType"></metadata-search> </div> </form> - <div class="ui horizontal divider"> - Or - </div> + <i18next tag="div" class="ui horizontal divider" path="Or"/> <form class="ui form" @submit.prevent=""> <div class="field"> - <label>Input a MusicBrainz ID manually:</label> + <i18next tag="label" path="Input a MusicBrainz ID manually:"/> <input type="text" v-model="currentId" /> </div> </form> <div class="ui hidden divider"></div> <template v-if="currentType && currentId"> - <h4 class="ui header">You will import:</h4> + <h4 class="ui header"><i18next path="You will import:"/></h4> <component :mbId="currentId" :is="metadataComponent" @metadata-changed="this.updateMetadata" ></component> </template> - <p>You can also skip this step and enter metadata manually.</p> + <i18next tag="p" path="You can also skip this step and enter metadata manually."/> </div> <div class="column"> <h5 class="ui header">What is metadata?</h5> - <p>Metadata is the data related to the music you want to import. This includes all the information about the artists, albums and tracks. In order to have a high quality library, it is recommended to grab data from the <a href="http://musicbrainz.org/" target="_blank">MusicBrainz project</a>, which you can think about as the Wikipedia of music.</p> + <i18next tag="p" path="Metadata is the data related to the music you want to import. This includes all the information about the artists, albums and tracks. In order to have a high quality library, it is recommended to grab data from the {%0%} project, which you can think about as the Wikipedia of music."> + <a href="http://musicbrainz.org/" target="_blank">MusicBrainz</a> + </i18next> </div> </div> <div v-if="currentStep === 2"> @@ -116,8 +118,8 @@ </div> </div> <div class="ui vertical stripe segment" v-if="currentRequest"> - <h3 class="ui header">Music request</h3> - <p>This import will be associated with the music request below. After the import is finished, the request will be marked as fulfilled.</p> + <h3 class="ui header"><i18next path="Music request"/></h3> + <i18next tag="p" path="This import will be associated with the music request below. After the import is finished, the request will be marked as fulfilled."/> <request-card :request="currentRequest" :import-action="false"></request-card> </div> diff --git a/front/src/components/library/import/ReleaseImport.vue b/front/src/components/library/import/ReleaseImport.vue index 51d5a2fead24a91a50eb2f31f931e93f91fe01e3..4b792b3921a2fa091c4db82962e24e0d93258bb4 100644 --- a/front/src/components/library/import/ReleaseImport.vue +++ b/front/src/components/library/import/ReleaseImport.vue @@ -1,13 +1,16 @@ <template> <div> <h3 class="ui dividing block header"> - Album <a :href="getMusicbrainzUrl('release', metadata.id)" target="_blank" title="View on MusicBrainz">{{ metadata.title }}</a> ({{ tracks.length}} tracks) by - <a :href="getMusicbrainzUrl('artist', metadata['artist-credit'][0]['artist']['id'])" target="_blank" title="View on MusicBrainz">{{ metadata['artist-credit-phrase'] }}</a> + <i18next path="Album {%0%} ({%1%} tracks) by {%2%}"> + <a :href="getMusicbrainzUrl('release', metadata.id)" target="_blank" title="View on MusicBrainz">{{ metadata.title }}</a> + ({{ tracks.length}} tracks) + <a :href="getMusicbrainzUrl('artist', metadata['artist-credit'][0]['artist']['id'])" target="_blank" title="View on MusicBrainz">{{ metadata['artist-credit-phrase'] }}</a> + </i18next> <div class="ui divider"></div> <div class="sub header"> <div class="ui toggle checkbox"> <input type="checkbox" v-model="enabled" /> - <label>Import this release</label> + <i18next tag="label" path="Import this release"/> </div> </div> </h3> diff --git a/front/src/components/library/import/TrackImport.vue b/front/src/components/library/import/TrackImport.vue index f6adc5afbbbc77c99cca36ae19b04d1a2c449a7d..abb526eff0a8dbf69f81397d0136272637418429 100644 --- a/front/src/components/library/import/TrackImport.vue +++ b/front/src/components/library/import/TrackImport.vue @@ -9,13 +9,13 @@ </h5> <div class="ui toggle checkbox"> <input type="checkbox" v-model="enabled" /> - <label>Import this track</label> + <i18next tag="label" path="Import this track"/> </div> </div> <div class="three wide column" v-if="enabled"> <form class="ui mini form" @submit.prevent=""> <div class="field"> - <label>Source</label> + <i18next tag="label" path="Source"/> <select v-model="currentBackendId"> <option v-for="backend in backends" :value="backend.id"> {{ backend.label }} @@ -28,7 +28,10 @@ <button @click="currentResultIndex -= 1" class="ui basic tiny icon button" :disabled="currentResultIndex === 0"> <i class="left arrow icon"></i> </button> - Result {{ currentResultIndex + 1 }}/{{ results.length }} + <i18next path="Result {%0%}/{%1%}"> + {{ currentResultIndex + 1 }} + {{ results.length }} + </i18next> <button @click="currentResultIndex += 1" class="ui basic tiny icon button" :disabled="currentResultIndex + 1 === results.length"> <i class="right arrow icon"></i> </button> @@ -37,9 +40,9 @@ <div class="four wide column" v-if="enabled"> <form class="ui mini form" @submit.prevent=""> <div class="field"> - <label>Search query</label> + <i18next tag="label" path="Search query"/> <input type="text" v-model="query" /> - <label>Imported URL</label> + <i18next tag="label" path="Imported URL"/> <input type="text" v-model="importedUrl" /> </div> </form> diff --git a/front/src/main.js b/front/src/main.js index d22825191863edbc7a217652a7ec727ef50a6c41..0c41294113929d4421a6ee36808be445de7ada5d 100644 --- a/front/src/main.js +++ b/front/src/main.js @@ -75,7 +75,7 @@ axios.interceptors.response.use(function (response) { } } if (error.backendErrors.length === 0) { - error.backendErrors.push('An unknown error occured, ensure your are connected to the internet and your funkwhale instance is up and running') + error.backendErrors.push(i18next.t('An unknown error occured, ensure your are connected to the internet and your funkwhale instance is up and running')) } // Do something with response error return Promise.reject(error) @@ -90,7 +90,11 @@ i18next fallbackLng: ['en'], preload: [navigator.language, 'en'], backend: { - loadPath: '/static/translations/{{lng}}.json' + loadPath: '/static/translations/{%lng%}.json' + }, + interpolation: { + prefix: '{%', + suffix: '%}' } }) const i18n = new VueI18Next(i18next) diff --git a/front/static/translations/fr.json b/front/static/translations/fr.json index 9b97d0eab8ea204287234f98290f09637f42fb13..f2729129d458d64293308d9f9534da92d707803a 100644 --- a/front/static/translations/fr.json +++ b/front/static/translations/fr.json @@ -1,3 +1,17 @@ { - "Hello, world!": "Bonjour tout le monde !" + "An unknown error occured, ensure your are connected to the internet and your funkwhale instance is up and running": "An unknown error occured, ensure your are connected to the internet and your funkwhale instance is up and running", + "Links": "Liens", + "About this instance": "À propos de cette instance", + "Official website": "Site officiel", + "Source code": "Source code", + "Issue tracker": "Issue tracker", + "About funkwhale": "About funkwhale", + "Funkwhale is a free and open-source project run by volunteers. You can help us improve the platform by reporting bugs, suggesting features and share the project with your friends!": "Funkwhale is a free and open-source project run by volunteers. You can help us improve the platform by reporting bugs, suggesting features and share the project with your friends!", + "The funkwhale logo was kindly designed and provided by Francis Gading.": "The funkwhale logo was kindly designed and provided by Francis Gading.", + "favorited a track": "favorited a track", + "from album {%album%}, by ": "from album {%album%}, by ", + ", by ": ", by ", + "listened to a track": "listened to a track", + "Show {%0%} more tracks": "Afficher {%0%} chansons supplémentaires", + "Collapse": "Masquer" } \ No newline at end of file diff --git a/po/fr.po b/po/fr.po index 95690711609e0206c7396bb209828ed0033910ec..9260a5a3e46837cf5f30bd637438c811a357a42d 100644 --- a/po/fr.po +++ b/po/fr.po @@ -12,5 +12,60 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -msgid "Hello, world!" -msgstr "Bonjour tout le monde !" +msgid "" +"An unknown error occured, ensure your are connected to the internet and your " +"funkwhale instance is up and running" +msgstr "" +"An unknown error occured, ensure your are connected to the internet and your " +"funkwhale instance is up and running" + +msgid "Links" +msgstr "Liens" + +msgid "About this instance" +msgstr "À propos de cette instance" + +msgid "Official website" +msgstr "Site officiel" + +msgid "Source code" +msgstr "Source code" + +msgid "Issue tracker" +msgstr "Issue tracker" + +msgid "About funkwhale" +msgstr "About funkwhale" + +msgid "" +"Funkwhale is a free and open-source project run by volunteers. You can help " +"us improve the platform by reporting bugs, suggesting features and share the " +"project with your friends!" +msgstr "" +"Funkwhale is a free and open-source project run by volunteers. You can help " +"us improve the platform by reporting bugs, suggesting features and share the " +"project with your friends!" + +msgid "The funkwhale logo was kindly designed and provided by Francis Gading." +msgstr "The funkwhale logo was kindly designed and provided by Francis Gading." + +msgid "favorited a track" +msgstr "favorited a track" + +msgid "from album {%album%}, by " +msgstr "from album {%album%}, by " + +msgid ", by " +msgstr ", by " + +msgid "listened to a track" +msgstr "listened to a track" + +msgid "Show {%0%} more tracks" +msgstr "Afficher {%0%} chansons supplémentaires" + +msgid "Collapse" +msgstr "Masquer" + +#~ msgid "Hello, world!" +#~ msgstr "Bonjour tout le monde !" diff --git a/po/funkwhale.pot b/po/funkwhale.pot index 131959d465fe55a72f76125e1e53cef20d8b0c5f..88ce3e676eccc00256ff387adc853c30c3d55cd3 100644 --- a/po/funkwhale.pot +++ b/po/funkwhale.pot @@ -12,5 +12,486 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" -msgid "Hello, world!" -msgstr "Hello, world!" +msgid "An unknown error occured, ensure your are connected to the internet and your funkwhale instance is up and running" +msgstr "An unknown error occured, ensure your are connected to the internet and your funkwhale instance is up and running" + +msgid "Links" +msgstr "Links" + +msgid "About this instance" +msgstr "About this instance" + +msgid "Official website" +msgstr "Official website" + +msgid "Source code" +msgstr "Source code" + +msgid "Issue tracker" +msgstr "Issue tracker" + +msgid "About funkwhale" +msgstr "About funkwhale" + +msgid "Funkwhale is a free and open-source project run by volunteers. You can help us improve the platform by reporting bugs, suggesting features and share the project with your friends!" +msgstr "Funkwhale is a free and open-source project run by volunteers. You can help us improve the platform by reporting bugs, suggesting features and share the project with your friends!" + +msgid "The funkwhale logo was kindly designed and provided by Francis Gading." +msgstr "The funkwhale logo was kindly designed and provided by Francis Gading." + +msgid "{%0%} favorited a track {%1%}" +msgstr "{%0%} favorited a track {%1%}" + +msgid "from album {%0%}, by {%1%}" +msgstr "from album {%0%}, by {%1%}" + +msgid ", by {%0%}" +msgstr ", by {%0%}" + +msgid "{%0%} listened to a track {%1%}" +msgstr "{%0%} listened to a track {%1%}" + +msgid "Show {%0%} more tracks" +msgstr "Show {%0%} more tracks" + +msgid "Collapse" +msgstr "Collapse" + +msgid "Play all" +msgstr "Play all" + +msgid "{%0%} tracks" +msgstr "{%0%} tracks" + +msgid "Show {%0%} more albums" +msgstr "Show {%0%} more albums" + +msgid "Title" +msgstr "Title" + +msgid "Artist" +msgstr "Artist" + +msgid "Album" +msgstr "Album" + +msgid "Download..." +msgstr "Download..." + +msgid "Download tracks" +msgstr "Download tracks" + +msgid "There is currently no way to download directly multiple tracks from funkwhale as a ZIP archive. However, you can use a command line tools such as {%0%} to easily download a list of tracks." +msgstr "There is currently no way to download directly multiple tracks from funkwhale as a ZIP archive. However, you can use a command line tools such as {%0%} to easily download a list of tracks." + +msgid "Simply copy paste the snippet below into a terminal to launch the download." +msgstr "Simply copy paste the snippet below into a terminal to launch the download." + +msgid "Keep your PRIVATE_TOKEN secret as it gives access to your account." +msgstr "Keep your PRIVATE_TOKEN secret as it gives access to your account." + +msgid "Cancel" +msgstr "Cancel" + +msgid "Add to current queue" +msgstr "Add to current queue" + +msgid "Play" +msgstr "Play" + +msgid "Add to queue" +msgstr "Add to queue" + +msgid "Play next" +msgstr "Play next" + +msgid "Play now" +msgstr "Play now" + +msgid "Previous track" +msgstr "Previous track" + +msgid "Play track" +msgstr "Play track" + +msgid "Pause track" +msgstr "Pause track" + +msgid "Next track" +msgstr "Next track" + +msgid "Unmute" +msgstr "Unmute" + +msgid "Mute" +msgstr "Mute" + +msgid "Looping disabled. Click to switch to single-track looping." +msgstr "Looping disabled. Click to switch to single-track looping." + +msgid "Looping on a single track. Click to switch to whole queue looping." +msgstr "Looping on a single track. Click to switch to whole queue looping." + +msgid "Looping on whole queue. Click to disable looping." +msgstr "Looping on whole queue. Click to disable looping." + +msgid "Shuffle your queue" +msgstr "Shuffle your queue" + +msgid "Clear your queue" +msgstr "Clear your queue" + +msgid "Search for some music" +msgstr "Search for some music" + +msgid "Artists" +msgstr "Artists" + +msgid "Sorry, we did not found any artist matching your query" +msgstr "Sorry, we did not found any artist matching your query" + +msgid "Albums" +msgstr "Albums" + +msgid "Sorry, we did not found any album matching your query" +msgstr "Sorry, we did not found any album matching your query" + +msgid "Log in to your Funkwhale account" +msgstr "Log in to your Funkwhale account" + +msgid "We cannot log you in" +msgstr "We cannot log you in" + +msgid "Please double-check your username/password couple is correct" +msgstr "Please double-check your username/password couple is correct" + +msgid "An unknown error happend, this can mean the server is down or cannot be reached" +msgstr "An unknown error happend, this can mean the server is down or cannot be reached" + +msgid "Username or email" +msgstr "Username or email" + +msgid "Password" +msgstr "Password" + +msgid "Login" +msgstr "Login" + +msgid "Create an account" +msgstr "Create an account" + +msgid "Are you sure you want to log out?" +msgstr "Are you sure you want to log out?" + +msgid "You are currently logged in as {%0%}" +msgstr "You are currently logged in as {%0%}" + +msgid "Yes, log me out!" +msgstr "Yes, log me out!" + +msgid "Registered since {%0%}" +msgstr "Registered since {%0%}" + +msgid "This is you!" +msgstr "This is you!" + +msgid "Staff member" +msgstr "Staff member" + +msgid "Settings..." +msgstr "Settings..." + +msgid "Account settings" +msgstr "Account settings" + +msgid "Settings updated" +msgstr "Settings updated" + +msgid "We cannot save your settings" +msgstr "We cannot save your settings" + +msgid "Update settings" +msgstr "Update settings" + +msgid "Change my password" +msgstr "Change my password" + +msgid "Cannot change your password" +msgstr "Cannot change your password" + +msgid "Please double-check your password is correct" +msgstr "Please double-check your password is correct" + +msgid "Old password" +msgstr "Old password" + +msgid "New password" +msgid "New password" + +msgid "Change password" +msgstr "Change password" + +msgid "Activity visibility" +msgstr "Activity visibility" + +msgid "Determine the visibility level of your activity" +msgstr "Determine the visibility level of your activity" + +msgid "Nobody except me" +msgstr "Nobody except me" + +msgid "Everyone on this instance" +msgstr "Everyone on this instance" + +msgid "Create a funkwhale account" +msgstr "Create a funkwhale account" + +msgid "We cannot create your account" +msgstr "We cannot create your account" + +msgid "Username" +msgstr "Username" + +msgid "Email" +msgstr "Email" + +msgid "Create my account" +msgstr "Create my account" + +msgid "Registration is currently disabled on this instance, please try again later." +msgstr "Registration is currently disabled on this instance, please try again later." + +msgid "Do you want to confirm this action?" +msgstr "Do you want to confirm this action?" + +msgid "Confirm" +msgstr "Confirm" + +msgid "Expand" +msgstr "Expand" + +msgid "Loading your favorites..." +msgstr "Loading your favorites..." + +msgid "{%0%} favorites" +msgstr "{%0%} favorites" + +msgid "Ordering" +msgstr "Ordering" + +msgid "Ordering direction" +msgstr "Ordering direction" + +msgid "Ascending" +msgstr "Ascending" + +msgid "Descending" +msgstr "Descending" + +msgid "Results per page" +msgstr "Results per page" + +msgid "Track name" +msgstr "Track name" + +msgid "Album name" +msgstr "Album name" + +msgid "Artist name" +msgstr "Artist name" + +msgid "In favorites" +msgstr "In favorites" + +msgid "Add to favorites" +msgstr "Add to favorites" + +msgid "Remove from favorites" +msgstr "Remove from favorites" + +msgid "User activity" +msgstr "User activity" + +msgid "users" +msgstr "users" + +msgid "tracks listened" +msgstr "tracks listened" + +msgid "Tracks favorited" +msgstr "Tracks favorited" + +msgid "hours of music" +msgstr "hours of music" + +msgid "Artists" +msgstr "Artists" + +msgid "Albums" +msgstr "Albums" + +msgid "tracks" +msgstr "tracks" + +msgid "Filter album types" +msgstr "Filter album types" + +msgid "Query template" +msgstr "Query template" + +msgid "Live" +msgstr "Live" + +msgid "Compilation" +msgstr "Compilation" + +msgid "EP" +msgstr "EP" + +msgid "Single" +msgstr "Single" + +msgid "Other" +msgstr "Other" + +msgid "Job ID" +msgstr "Job ID" + +msgid "Recording MusicBrainz ID" +msgstr "Recording MusicBrainz ID" + +msgid "Source" +msgstr "Source" + +msgid "Track" +msgstr "Track" + +msgid "Previous" +msgstr "Previous" + +msgid "Next" +msgstr "Next" + +msgid "ID" +msgstr "ID" + +msgid "Launch date" +msgstr "Launch date" + +msgid "Jobs" +msgstr "Jobs" + +msgid "Status" +msgstr "Status" + +msgid "Select files to upload..." +msgstr "Select files to upload..." + +msgid "Start Upload" +msgstr "Start Upload" + +msgid "Stop Upload" +msgstr "Stop Upload" + +msgid "Once all your files are uploaded, simply head over {%0%} to check the import status." +msgstr "Once all your files are uploaded, simply head over {%0%} to check the import status." + +msgid "import detail page" +msgstr "import detail page" + +msgid "File name" +msgstr "File name" + +msgid "Size" +msgstr "Size" + +msgid "Success" +msgstr "Success" + +msgid "Uploading..." +msgstr "Uploading..." + +msgid "Pending" +msgstr "Pending" + +msgid "Import source" +msgstr "Import source" + +msgid "Uploaded files or external source" +msgstr "Uploaded files or external source" + +msgid "Metadata" +msgstr "Metadata" + +msgid "Grab corresponding metadata" +msgstr "Grab corresponding metadata" + +msgid "Music" +msgstr "Music" + +msgid "Select relevant sources or files for import" +msgstr "Select relevant sources or files for import" + +msgid "Previous step" +msgstr "Previous step" + +msgid "Next step" +msgstr "Next step" + +msgid "Import {%0%} tracks" +msgstr "Import {%0%} tracks" + +msgid "First, choose where you want to import the music from:" +msgstr "First, choose where you want to import the music from:" + +msgid "External source. Supported backends:" +msgstr "External source. Supported backends:" + +msgid "File upload" +msgstr "File upload" + +msgid "Search an entity you want to import:" +msgstr "Search an entity you want to import:" + +msgid "Input a MusicBrainz ID manually:" +msgstr "Input a MusicBrainz ID manually:" + +msgid "Or" +msgstr "Or" + +msgid "You will import:" +msgstr "You will import:" + +msgid "You can also skip this step and enter metadata manually." +msgstr "You can also skip this step and enter metadata manually." + +msgid "Metadata is the data related to the music you want to import. This includes all the information about the artists, albums and tracks. In order to have a high quality library, it is recommended to grab data from the {%0%} project, which you can think about as the Wikipedia of music." +msgstr "Metadata is the data related to the music you want to import. This includes all the information about the artists, albums and tracks. In order to have a high quality library, it is recommended to grab data from the {%0%} project, which you can think about as the Wikipedia of music." + +msgid "Music request" +msgstr "Music request" + +msgid "This import will be associated with the music request below. After the import is finished, the request will be marked as fulfilled." +msgstr "This import will be associated with the music request below. After the import is finished, the request will be marked as fulfilled." + +msgid "Album {%0%} ({%1%} tracks) by {%2%}" +msgstr "Album {%0%} ({%1%} tracks) by {%2%}" + +msgid "Import this release" +msgstr "Import this release" + +msgid "Import this track" +msgstr "Import this track" + +msgid "Source" +msgstr "Source" + +msgid "Result {%0%}/{%1%}" +msgstr "Result {%0%}/{%1%}" + +msgid "Search query" +msgstr "Search query" + +msgid "Imported URL" +msgstr "Imported URL" +