diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
index f92d73438b486c73f00f0492ce18175c4a99401d..05254b76d25c48094b827310b41f2c6f16aec322 100644
--- a/CONTRIBUTING.rst
+++ b/CONTRIBUTING.rst
@@ -442,6 +442,7 @@ This hierarchical structure is made of several parts:
     - ``Admin``
     - ``Album``
     - ``Artist``
+    - ``Embed``
     - ``Home``
     - ``Login``
     - ``Library``
@@ -451,6 +452,7 @@ This hierarchical structure is made of several parts:
     - ``Favorites``
     - ``Notifications``
     - ``Radio``
+    - ``Search``
     - ``Settings``
     - ``Signup``
     - ``Track``
diff --git a/front/src/components/audio/EmbedWizard.vue b/front/src/components/audio/EmbedWizard.vue
index 7a50ffa54223a189d40cd91fbbe9f0e41b0814ee..f919ec5cd9a9c87ab3f8eeed97f0dea1ab617e63 100644
--- a/front/src/components/audio/EmbedWizard.vue
+++ b/front/src/components/audio/EmbedWizard.vue
@@ -4,22 +4,22 @@
       <div class="two fields">
         <div class="field">
           <div class="field">
-            <label for="embed-width"><translate>Widget width</translate></label>
-            <p><translate>Leave empty for a responsive widget</translate></p>
+            <label for="embed-width"><translate :translate-context="'Popup/Embed/Input.Label'">Widget width</translate></label>
+            <p><translate :translate-context="'Popup/Embed/Paragraph'">Leave empty for a responsive widget</translate></p>
             <input id="embed-width" type="number" v-model.number="width" min="0" step="10" />
           </div>
           <template v-if="type != 'track'">
             <br>
             <div class="field">
-              <label for="embed-height"><translate>Widget height</translate></label>
+              <label for="embed-height"><translate :translate-context="'Popup/Embed/Input.Label'">Widget height</translate></label>
               <input id="embed-height" type="number" v-model="height" :min="minHeight" max="1000" step="10" />
             </div>
           </template>
         </div>
         <div class="field">
-          <button @click="copy" class="ui right floated button"><translate>Copy</translate></button>
-          <label for="embed-width"><translate>Embed code</translate></label>
-          <p><translate>Copy/paste this code in your website HTML</translate></p>
+          <button @click="copy" class="ui right floated button"><translate :translate-context="'Popup/*/Button.Label/Verb'">Copy</translate></button>
+          <label for="embed-width"><translate :translate-context="'Popup/Embed/Input.Label/Noun'">Embed code</translate></label>
+          <p><translate :translate-context="'Popup/Embed/Paragraph'">Copy/paste this code in your website HTML</translate></p>
           <div class="ui hidden divider"></div>
           <textarea ref="textarea":value="embedCode" rows="3" readonly>
           </textarea>
@@ -27,7 +27,7 @@
       </div>
     </div>
     <div class="preview">
-      <h3><translate>Preview</translate></h3>
+      <h3><translate :translate-context="'Popup/Embed/Title/Noun'">Preview</translate></h3>
       <iframe :width="frameWidth" :height="height" scrolling="no" frameborder="no" :src="iframeSrc"></iframe>
     </div>
   </div>
diff --git a/front/src/components/audio/PlayButton.vue b/front/src/components/audio/PlayButton.vue
index 425d0a1d73792fe6f5fcdc642678391e4f382d9f..a84ee67d5d25cd809cd08c5d34b0dfe0d5b465a2 100644
--- a/front/src/components/audio/PlayButton.vue
+++ b/front/src/components/audio/PlayButton.vue
@@ -7,22 +7,22 @@
       :disabled="!playable"
       :class="buttonClasses.concat(['ui', {loading: isLoading}, {'mini': discrete}, {disabled: !playable}])">
       <i :class="[playIconClass, 'icon']"></i>
-      <template v-if="!discrete && !iconOnly"><slot><translate :v-context="'*/Queue/Button/Label/Short, Verb'">Play</translate></slot></template>
+      <template v-if="!discrete && !iconOnly"><slot><translate :translate-context="'*/Queue/Button/Label/Short, Verb'">Play</translate></slot></template>
     </button>
     <div v-if="!discrete && !iconOnly" :class="['ui', {disabled: !playable}, 'floating', 'dropdown', {'icon': !dropdownOnly}, {'button': !dropdownOnly}]">
       <i :class="dropdownIconClasses.concat(['icon'])"></i>
       <div class="menu">
         <button class="item basic" ref="add" data-ref="add" :disabled="!playable" @click.stop.prevent="add" :title="labels.addToQueue">
-          <i class="plus icon"></i><translate :v-context="'*/Queue/Dropdown/Button/Label/Short'">Add to queue</translate>
+          <i class="plus icon"></i><translate :translate-context="'*/Queue/Dropdown/Button/Label/Short'">Add to queue</translate>
         </button>
         <button class="item basic" ref="addNext" data-ref="addNext" :disabled="!playable" @click.stop.prevent="addNext()" :title="labels.playNext">
-          <i class="step forward icon"></i><translate :v-context="'*/Queue/Dropdown/Button/Label/Short'">Play next</translate>
+          <i class="step forward icon"></i><translate :translate-context="'*/Queue/Dropdown/Button/Label/Short'">Play next</translate>
         </button>
         <button class="item basic" ref="playNow" data-ref="playNow" :disabled="!playable" @click.stop.prevent="addNext(true)" :title="labels.playNow">
-          <i class="play icon"></i><translate :v-context="'*/Queue/Dropdown/Button/Label/Short'">Play now</translate>
+          <i class="play icon"></i><translate :translate-context="'*/Queue/Dropdown/Button/Label/Short'">Play now</translate>
         </button>
         <button v-if="track" class="item basic" :disabled="!playable" @click.stop.prevent="$store.dispatch('radios/start', {type: 'similar', objectId: track.id})" :title="labels.startRadio">
-          <i class="feed icon"></i><translate :v-context="'*/Queue/Dropdown/Button/Label/Short'">Start radio</translate>
+          <i class="feed icon"></i><translate :translate-context="'*/Queue/Dropdown/Button/Label/Short'">Start radio</translate>
         </button>
       </div>
     </div>
diff --git a/front/src/components/audio/Player.vue b/front/src/components/audio/Player.vue
index 575f6873662aa851bc83cd623226ff5259c88329..5df3248bf36da2a461ecb89a5f9e1b252282d10f 100644
--- a/front/src/components/audio/Player.vue
+++ b/front/src/components/audio/Player.vue
@@ -62,14 +62,14 @@
       </div>
       <div class="ui small warning message" v-if="currentTrack && errored">
         <div class="header">
-          <translate>We cannot load this track</translate>
+          <translate :translate-context="'Sidebar/Player/Error message.Title'">The track cannot be loaded</translate>
         </div>
         <p v-if="hasNext && playing && $store.state.player.errorCount < $store.state.player.maxConsecutiveErrors">
-          <translate>The next track will play automatically in a few seconds…</translate>
+          <translate :translate-context="'Sidebar/Player/Error message.Paragraph'">The next track will play automatically in a few seconds…</translate>
           <i class="loading spinner icon"></i>
         </p>
         <p>
-          <translate>You may have a connectivity issue.</translate>
+          <translate :translate-context="'Sidebar/Player/Error message.Paragraph'">You may have a connectivity issue.</translate>
         </p>
       </div>
       <div class="two wide column controls ui grid">
@@ -280,7 +280,7 @@ export default {
         return
       }
       let self = this
-      let msg = this.$gettext("Queue shuffled!")
+      let msg = this.$pgettext('Content/Queue/Message', "Queue shuffled!")
       this.isShuffling = true
       setTimeout(() => {
         self.$store.dispatch("queue/shuffle", () => {
@@ -346,24 +346,24 @@ export default {
       progress: "player/progress"
     }),
     labels() {
-      let audioPlayer = this.$gettext("Media player")
-      let previousTrack = this.$gettext("Previous track")
-      let play = this.$gettext("Play track")
-      let pause = this.$gettext("Pause track")
-      let next = this.$gettext("Next track")
-      let unmute = this.$gettext("Unmute")
-      let mute = this.$gettext("Mute")
-      let loopingDisabled = this.$gettext(
+      let audioPlayer = this.$pgettext('Sidebar/Player/Hidden text', "Media player")
+      let previousTrack = this.$pgettext('Sidebar/Player/Icon.Tooltip', "Previous track")
+      let play = this.$pgettext('Sidebar/Player/Icon.Tooltip/Verb', "Play track")
+      let pause = this.$pgettext('Sidebar/Player/Icon.Tooltip/Verb', "Pause track")
+      let next = this.$pgettext('Sidebar/Player/Icon.Tooltip', "Next track")
+      let unmute = this.$pgettext('Sidebar/Player/Icon.Tooltip/Verb', "Unmute")
+      let mute = this.$pgettext('Sidebar/Player/Icon.Tooltip/Verb', "Mute")
+      let loopingDisabled = this.$pgettext('Sidebar/Player/Icon.Tooltip', 
         "Looping disabled. Click to switch to single-track looping."
       )
-      let loopingSingle = this.$gettext(
+      let loopingSingle = this.$pgettext('Sidebar/Player/Icon.Tooltip', 
         "Looping on a single track. Click to switch to whole queue looping."
       )
-      let loopingWhole = this.$gettext(
+      let loopingWhole = this.$pgettext('Sidebar/Player/Icon.Tooltip', 
         "Looping on whole queue. Click to disable looping."
       )
-      let shuffle = this.$gettext("Shuffle your queue")
-      let clear = this.$gettext("Clear your queue")
+      let shuffle = this.$pgettext('Sidebar/Player/Icon.Tooltip/Verb', "Shuffle your queue")
+      let clear = this.$pgettext('Sidebar/Player/Icon.Tooltip/Verb', "Clear your queue")
       return {
         audioPlayer,
         previousTrack,
diff --git a/front/src/components/audio/Search.vue b/front/src/components/audio/Search.vue
index dd250ca09f08bbd1c27a946747a7bb72462e70f6..7c3c540ca1b478f93675cc6e08e60b3d5e545a7e 100644
--- a/front/src/components/audio/Search.vue
+++ b/front/src/components/audio/Search.vue
@@ -1,6 +1,6 @@
 <template>
   <div>
-    <h2><translate>Search for some music</translate></h2>
+    <h2><translate :translate-context="'Content/Search/Title'">Search for some music</translate></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"><translate>Artists</translate></h3>
+      <h3 class="ui title"><translate :translate-context="'Content/Search/Title'">Artists</translate></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><translate>No artist matched your query</translate></p>
+      <p v-else><translate :translate-context="'Content/Search/Paragraph'">No artist matched your query</translate></p>
     </template>
     <template v-if="query.length > 0">
-      <h3 class="ui title"><translate>Albums</translate></h3>
+      <h3 class="ui title"><translate :translate-context="'Content/Search/Title'">Albums</translate></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><translate>No album matched your query</translate></p>
+      <p v-else><translate :translate-context="'Content/Search/Paragraph'">No album matched your query</translate></p>
     </template>
   </div>
 </template>
@@ -62,7 +62,7 @@ export default {
   computed: {
     labels () {
       return {
-        searchPlaceholder: this.$gettext('Artist, album, track…')
+        searchPlaceholder: this.$pgettext('*/Search/Input.Placeholder', 'Artist, album, track…')
       }
     }
   },
diff --git a/front/src/components/audio/SearchBar.vue b/front/src/components/audio/SearchBar.vue
index 534ac0ac4f3862170a9b2a649a1746bba783cb0e..c1190f474d653107ce0d73066200011a7c7ff450 100644
--- a/front/src/components/audio/SearchBar.vue
+++ b/front/src/components/audio/SearchBar.vue
@@ -17,14 +17,14 @@ export default {
   computed: {
     labels () {
       return {
-        placeholder: this.$gettext('Search for artists, albums, tracks…')
+        placeholder: this.$pgettext('Sidebar/Search/Input.Placeholder', 'Search for artists, albums, tracks…')
       }
     }
   },
   mounted () {
-    let artistLabel = this.$gettext('Artist')
-    let albumLabel = this.$gettext('Album')
-    let trackLabel = this.$gettext('Track')
+    let artistLabel = this.$pgettext('Sidebar/Search/Title', 'Artist')
+    let albumLabel = this.$pgettext('Sidebar/Search/Title', 'Album')
+    let trackLabel = this.$pgettext('Sidebar/Search/Title', 'Track')
     let self = this
     jQuery(this.$el).search({
       type: 'category',
diff --git a/front/src/components/audio/album/Card.vue b/front/src/components/audio/album/Card.vue
index 2f19d7fbb4854f7c248726f64290d026bf087281..75505d6f922b7130b3fe26d1be20c27ff553b399 100644
--- a/front/src/components/audio/album/Card.vue
+++ b/front/src/components/audio/album/Card.vue
@@ -11,7 +11,7 @@
         <div class="meta">
           <span>
             <router-link tag="span" :to="{name: 'library.artists.detail', params: {id: album.artist.id }}">
-              <translate :translate-params="{artist: album.artist.name}">By %{ artist }</translate>
+              <translate :translate-context="'Content/Album/Card'" :translate-params="{artist: album.artist.name}">By %{ artist }</translate>
             </router-link>
           </span><span class="time" v-if="album.release_date">– {{ album.release_date | year }}</span>
         </div>
@@ -36,21 +36,21 @@
           </table>
           <div class="center aligned segment" v-if="album.tracks.length > initialTracks">
             <em v-if="!showAllTracks" @click="showAllTracks = true" class="expand">
-              <translate :translate-params="{count: album.tracks.length - initialTracks}" :translate-n="album.tracks.length - initialTracks" translate-plural="Show %{ count } more tracks">Show %{ count } more track</translate>
+              <translate :translate-context="'Content/Album/Card.Link/Verb'" :translate-params="{count: album.tracks.length - initialTracks}" :translate-n="album.tracks.length - initialTracks" translate-plural="Show %{ count } more tracks">Show %{ count } more track</translate>
             </em>
             <em v-else @click="showAllTracks = false" class="expand">
-              <translate>Collapse</translate>
+              <translate :translate-context="'Content/Album/Card.Link/Verb'">Collapse</translate>
             </em>
           </div>
         </div>
       </div>
       <div class="extra content">
         <play-button class="mini basic orange right floated" :tracks="album.tracks">
-          <translate>Play all</translate>
+          <translate :translate-context="'Content/Queue/Card.Button.Label/Short, Verb'">Play all</translate>
         </play-button>
         <span>
           <i class="music icon"></i>
-          <translate :translate-params="{count: album.tracks.length}" :translate-n="album.tracks.length" translate-plural="%{ count } tracks">%{ count } track</translate>
+          <translate :translate-context="'Content/Album/Card'" :translate-params="{count: album.tracks.length}" :translate-n="album.tracks.length" translate-plural="%{ count } tracks">%{ count } track</translate>
         </span>
       </div>
     </div>
diff --git a/front/src/components/audio/artist/Card.vue b/front/src/components/audio/artist/Card.vue
index 1876c42c01f1d62bb567f6600ea872b19bf105f6..82af12524c20b24f7f8c80f894dfb46f605676fb 100644
--- a/front/src/components/audio/artist/Card.vue
+++ b/front/src/components/audio/artist/Card.vue
@@ -28,10 +28,10 @@
           </table>
           <div class="center aligned segment" v-if="artist.albums.length > initialAlbums">
             <em v-if="!showAllAlbums" @click="showAllAlbums = true" class="expand">
-              <translate :translate-params="{count: artist.albums.length - initialAlbums}" :translate-n="artist.albums.length - initialAlbums" translate-plural="Show %{ count } more albums">Show 1 more album</translate>
+              <translate :translate-context="'Content/Artist/Card.Link'" :translate-params="{count: artist.albums.length - initialAlbums}" :translate-n="artist.albums.length - initialAlbums" translate-plural="Show %{ count } more albums">Show 1 more album</translate>
             </em>
             <em v-else @click="showAllAlbums = false" class="expand">
-              <translate>Collapse</translate>
+              <translate :translate-context="'Content/Artist/Card.Link'">Collapse</translate>
             </em>
           </div>
         </div>
@@ -39,10 +39,10 @@
     <div class="extra content">
         <span>
           <i class="sound icon"></i>
-            <translate :translate-params="{count: artist.albums.length}" :translate-n="artist.albums.length" translate-plural="%{ count } albums">1 album</translate>
+            <translate :translate-context="'Content/Artist/Card'" :translate-params="{count: artist.albums.length}" :translate-n="artist.albums.length" translate-plural="%{ count } albums">1 album</translate>
         </span>
         <play-button :is-playable="isPlayable" class="mini basic orange right floated" :artist="artist.id">
-          <translate>Play all</translate>
+          <translate :translate-context="'Content/Queue/Button.Label/Short, Verb'">Play all</translate>
         </play-button>
       </div>
     </div>
diff --git a/front/src/components/audio/track/Row.vue b/front/src/components/audio/track/Row.vue
index d3b7dc734b91b528561c764873de1a75e53b9317..e3005c388a3604b471eeab895713fdd44f7782ad 100644
--- a/front/src/components/audio/track/Row.vue
+++ b/front/src/components/audio/track/Row.vue
@@ -38,7 +38,7 @@
       {{ time.parse(track.uploads[0].duration) }}
     </td>
     <td colspan="4" v-else>
-      <translate>N/A</translate>
+      <translate :translate-context="'*/*/*'">N/A</translate>
     </td>
     <td colspan="2">
       <track-favorite-icon class="favorite-icon" :track="track"></track-favorite-icon>
diff --git a/front/src/components/audio/track/Table.vue b/front/src/components/audio/track/Table.vue
index 937025807864f950f3c4dae60a503c7ca8b29f54..1134e88a8ae04dfbcde68abeba59546bc46bc6c4 100644
--- a/front/src/components/audio/track/Table.vue
+++ b/front/src/components/audio/track/Table.vue
@@ -4,10 +4,10 @@
       <tr>
         <th></th>
         <th></th>
-        <th colspan="6"><translate>Title</translate></th>
-        <th colspan="4"><translate>Artist</translate></th>
-        <th colspan="4"><translate>Album</translate></th>
-        <th colspan="4"><translate>Duration</translate></th>
+        <th colspan="6"><translate :translate-context="'Content/Track/Table.Label'">Title</translate></th>
+        <th colspan="4"><translate :translate-context="'Content/Track/Table.Label'">Artist</translate></th>
+        <th colspan="4"><translate :translate-context="'Content/Track/Table.Label'">Album</translate></th>
+        <th colspan="4"><translate :translate-context="'Content/Track/Table.Label'">Duration</translate></th>
         <th colspan="2"></th>
       </tr>
     </thead>
diff --git a/front/src/components/playlists/Card.vue b/front/src/components/playlists/Card.vue
index 344eb5fbf9ecbc17e7d744d85cdb4efdf2b3d17e..70ac34097aa176f39c59d2caf1ed3ca3e1fa0149 100644
--- a/front/src/components/playlists/Card.vue
+++ b/front/src/components/playlists/Card.vue
@@ -16,7 +16,7 @@
         <duration :seconds="playlist.duration" />
          |
         <i class="sound icon"></i>
-        <translate
+        <translate :translate-context="'Content/*/Card/List item'"
           translate-plural="%{ count } tracks"
           :translate-n="playlist.tracks_count"
           :translate-params="{count: playlist.tracks_count}">
diff --git a/front/src/components/playlists/Editor.vue b/front/src/components/playlists/Editor.vue
index 5b5311f145e593d25062b2895bf4ae140e8ff94c..fee9ef6b0baa5d940941f42a74cb415f01070a16 100644
--- a/front/src/components/playlists/Editor.vue
+++ b/front/src/components/playlists/Editor.vue
@@ -2,16 +2,16 @@
   <div class="ui text container">
     <playlist-form @updated="$emit('playlist-updated', $event)" :title="false" :playlist="playlist"></playlist-form>
     <h3 class="ui top attached header">
-      <translate>Playlist editor</translate>
+      <translate :translate-context="'Content/Playlist/Title'">Playlist editor</translate>
     </h3>
     <div class="ui attached segment">
       <template v-if="status === 'loading'">
         <div class="ui active tiny inline loader"></div>
-        <translate>Syncing changes to server…</translate>
+        <translate :translate-context="'Content/Playlist/Paragraph'">Syncing changes to server…</translate>
       </template>
       <template v-else-if="status === 'errored'">
         <i class="red close icon"></i>
-        <translate>An error occured while saving your changes</translate>
+        <translate :translate-context="'Content/Playlist/Error message.Title'">An error occured while saving your changes</translate>
         <div v-if="errors.length > 0" class="ui negative message">
           <ul class="list">
             <li v-for="error in errors">{{ error }}</li>
@@ -19,7 +19,7 @@
         </div>
       </template>
       <template v-else-if="status === 'saved'">
-        <i class="green check icon"></i> <translate>Changes synced with server</translate>
+        <i class="green check icon"></i> <translate :translate-context="'Content/Playlist/Paragraph'">Changes synced with server</translate>
       </template>
     </div>
     <div class="ui bottom attached segment">
@@ -29,7 +29,7 @@
         :class="['ui', {disabled: queueTracks.length === 0}, 'labeled', 'icon', 'button']"
         :title="labels.copyTitle">
           <i class="plus icon"></i>
-          <translate
+          <translate :translate-context="'Content/Playlist/Button.Label/Verb'"
             translate-plural="Insert from queue (%{ count } tracks)"
             :translate-n="queueTracks.length"
             :translate-params="{count: queueTracks.length}">
@@ -38,16 +38,16 @@
         </div>
 
       <dangerous-button :disabled="plts.length === 0" class="labeled right floated icon" color='yellow' :action="clearPlaylist">
-        <i class="eraser icon"></i> <translate>Clear playlist</translate>
+        <i class="eraser icon"></i> <translate :translate-context="'Content/Playlist/Button.Label/Verb'">Clear playlist</translate>
         <p slot="modal-header">
-          <translate :translate-params="{playlist: playlist.name}">Do you want to clear the playlist "%{ playlist }"?</translate>
+          <translate :translate-context="'Popup/Playlist/Title'" :translate-params="{playlist: playlist.name}">Do you want to clear the playlist "%{ playlist }"?</translate>
         </p>
-        <p slot="modal-content"><translate>This will remove all tracks from this playlist and cannot be undone.</translate></p>
-        <p slot="modal-confirm"><translate>Clear playlist</translate></p>
+        <p slot="modal-content"><translate :translate-context="'Popup/Playlist/Paragraph'">This will remove all tracks from this playlist and cannot be undone.</translate></p>
+        <p slot="modal-confirm"><translate :translate-context="'Popup/Playlist/Button.Label'">Clear playlist</translate></p>
       </dangerous-button>
       <div class="ui hidden divider"></div>
       <template v-if="plts.length > 0">
-        <p><translate>Drag and drop rows to reorder tracks in the playlist</translate></p>
+        <p><translate :translate-context="'Content/Playlist/Paragraph/Call to action'">Drag and drop rows to reorder tracks in the playlist</translate></p>
         <table class="ui compact very basic fixed single line unstackable table">
           <draggable v-model="plts" element="tbody" @update="reorder">
             <tr v-for="(plt, index) in plts" :key="plt.id">
@@ -160,7 +160,7 @@ export default {
     }),
     labels () {
       return {
-        copyTitle: this.$gettext('Copy queued tracks to playlist')
+        copyTitle: this.$pgettext('Content/Playlist/Button.Tooltip/Verb', 'Copy queued tracks to playlist')
       }
     },
     status () {
diff --git a/front/src/components/playlists/Form.vue b/front/src/components/playlists/Form.vue
index 1fe9740654192adcdbbc22872dbae38217d976d7..058a6fd114f0e46f32e05decdf324a5333360885 100644
--- a/front/src/components/playlists/Form.vue
+++ b/front/src/components/playlists/Form.vue
@@ -1,29 +1,29 @@
 <template>
   <form class="ui form" @submit.prevent="submit()">
-    <h4 v-if="title" class="ui header"><translate>Create a new playlist</translate></h4>
+    <h4 v-if="title" class="ui header"><translate :translate-context="'Popup/Playlist/Title/Verb'">Create a new playlist</translate></h4>
     <div v-if="success" class="ui positive message">
       <div class="header">
         <template v-if="playlist">
-          <translate>Playlist updated</translate>
+          <translate :translate-context="'Content/Playlist/Message'">Playlist updated</translate>
         </template>
         <template v-else>
-          <translate>Playlist created</translate>
+          <translate :translate-context="'Content/Playlist/Message'">Playlist created</translate>
         </template>
       </div>
     </div>
     <div v-if="errors.length > 0" class="ui negative message">
-      <div class="header"><translate>We cannot create the playlist</translate></div>
+      <div class="header"><translate :translate-context="'Content/Playlist/Error message.Title'">The playlist could not be created</translate></div>
       <ul class="list">
         <li v-for="error in errors">{{ error }}</li>
       </ul>
     </div>
     <div class="three fields">
       <div class="field">
-        <label><translate>Playlist name</translate></label>
+        <label><translate :translate-context="'Content/Playlist/Input.Label'">Playlist name</translate></label>
         <input name="name" v-model="name" required type="text" :placeholder="labels.placeholder" />
       </div>
       <div class="field">
-        <label><translate>Playlist visibility</translate></label>
+        <label><translate :translate-context="'Content/Playlist/Dropdown.Label'">Playlist visibility</translate></label>
         <select class="ui dropdown" v-model="privacyLevel">
           <option :value="c.value" v-for="c in privacyLevelChoices">{{ c.label }}</option>
         </select>
@@ -31,8 +31,8 @@
       <div class="field">
         <label>&nbsp;</label>
         <button :class="['ui', 'fluid', {'loading': isLoading}, 'button']" type="submit">
-          <template v-if="playlist"><translate>Update playlist</translate></template>
-          <template v-else><translate>Create playlist</translate></template>
+          <template v-if="playlist"><translate :translate-context="'Content/Playlist/Button.Label/Verb'">Update playlist</translate></template>
+          <template v-else><translate :translate-context="'Content/Playlist/Button.Label/Verb'">Create playlist</translate></template>
         </button>
       </div>
     </div>
@@ -71,22 +71,22 @@ export default {
   computed: {
     labels () {
       return {
-        placeholder: this.$gettext('My awesome playlist')
+        placeholder: this.$pgettext('Content/Playlist/Input.Placeholder', 'My awesome playlist')
       }
     },
     privacyLevelChoices: function () {
       return [
         {
           value: 'me',
-          label: this.$gettext('Nobody except me')
+          label: this.$pgettext('Content/Playlist/Dropdown', 'Nobody except me')
         },
         {
           value: 'instance',
-          label: this.$gettext('Everyone on this instance')
+          label: this.$pgettext('Content/Playlist/Dropdown', 'Everyone on this instance')
         },
         {
           value: 'everyone',
-          label: this.$gettext('Everyone')
+          label: this.$pgettext('Content/Playlist/Dropdown', 'Everyone')
         }
       ]
     }
diff --git a/front/src/components/playlists/PlaylistModal.vue b/front/src/components/playlists/PlaylistModal.vue
index 3065631afb376deb5473d98188c81daf6a903aaf..3707e3d2cba6837e96cc653a738e51c85d07c1a7 100644
--- a/front/src/components/playlists/PlaylistModal.vue
+++ b/front/src/components/playlists/PlaylistModal.vue
@@ -1,13 +1,13 @@
 <template>
   <modal @update:show="update" :show="$store.state.playlists.showModal">
     <div class="header">
-      <translate>Manage playlists</translate>
+      <translate :translate-context="'Popup/Playlist/Title/Verb'">Manage playlists</translate>
     </div>
     <div class="scrolling content">
       <div class="description">
         <template v-if="track">
-          <h4 class="ui header"><translate>Current track</translate></h4>
-          <translate
+          <h4 class="ui header"><translate :translate-context="'Popup/Playlist/Title'">Current track</translate></h4>
+          <translate :translate-context="'Popup/Playlist/Paragraph'"
             v-translate="{artist: track.artist.name, title: track.title}"
             :translate-params="{artist: track.artist.name, title: track.title}">
             "%{ title }", by %{ artist }
@@ -18,20 +18,20 @@
         <playlist-form :key="formKey"></playlist-form>
         <div class="ui divider"></div>
         <div v-if="errors.length > 0" class="ui negative message">
-          <div class="header"><translate>We cannot add the track to a playlist</translate></div>
+          <div class="header"><translate :translate-context="'Popup/Playlist/Error message.Title'">The track can't be added to a playlist</translate></div>
           <ul class="list">
             <li v-for="error in errors">{{ error }}</li>
           </ul>
         </div>
         </div>
-        <h4 class="ui header"><translate>Available playlists</translate></h4>
+        <h4 class="ui header"><translate :translate-context="'Popup/Playlist/Title'">Available playlists</translate></h4>
         <table class="ui unstackable very basic table">
           <thead>
             <tr>
               <th></th>
-              <th><translate>Name</translate></th>
-              <th class="sorted descending"><translate>Last modification</translate></th>
-              <th><translate>Tracks</translate></th>
+              <th><translate :translate-context="'*/*/Table.Label'">Name</translate></th>
+              <th class="sorted descending"><translate :translate-context="'Popup/Playlist/Table.Label/Short'">Last modification</translate></th>
+              <th><translate :translate-context="'*/*/Table.Label'">Tracks</translate></th>
               <th></th>
             </tr>
           </thead>
@@ -52,7 +52,7 @@
                   class="ui green icon basic small right floated button"
                   :title="labels.addToPlaylist"
                   @click="addToPlaylist(playlist.id)">
-                  <i class="plus icon"></i> <translate>Add track</translate>
+                  <i class="plus icon"></i> <translate :translate-context="'Popup/Playlist/Table.Button.Label/Verb'">Add track</translate>
                 </div>
               </td>
             </tr>
@@ -61,7 +61,7 @@
       </div>
     </div>
     <div class="actions">
-      <div class="ui cancel button"><translate>Cancel</translate></div>
+      <div class="ui cancel button"><translate :translate-context="'Popup/Playlist/Button.Label'">Cancel</translate></div>
     </div>
   </modal>
 </template>
@@ -113,7 +113,7 @@ export default {
     }),
     labels () {
       return {
-        addToPlaylist: this.$gettext('Add to this playlist')
+        addToPlaylist: this.$pgettext('Popup/Playlist/Table.Button.Tooltip/Verb', 'Add to this playlist')
       }
     },
     sortedPlaylists () {
diff --git a/front/src/components/playlists/TrackPlaylistIcon.vue b/front/src/components/playlists/TrackPlaylistIcon.vue
index 8487e6777b23c181749e8b8764fdc79bfeb7dc61..3777318f167b87109198ced8e211dab530aaf855 100644
--- a/front/src/components/playlists/TrackPlaylistIcon.vue
+++ b/front/src/components/playlists/TrackPlaylistIcon.vue
@@ -4,7 +4,7 @@
     v-if="button"
     :class="['ui', 'button']">
     <i class="list icon"></i>
-    <translate>Add to playlist…</translate>
+    <translate :translate-context="'Sidebar/Player/Icon.Tooltip/Verb'">Add to playlist…</translate>
   </button>
   <button
     v-else
@@ -31,7 +31,7 @@ export default {
   computed: {
     labels () {
       return {
-        addToPlaylist: this.$gettext('Add to playlist…')
+        addToPlaylist: this.$pgettext('Sidebar/Player/Icon.Tooltip/Verb', 'Add to playlist…')
       }
     }
   }
diff --git a/front/src/views/radios/Detail.vue b/front/src/views/radios/Detail.vue
index 0c46385a6bab53f50f96d65acd491ac6c287e4c3..88c5e892fbd632ca773aee9f2b58c2fa5ed18b17 100644
--- a/front/src/views/radios/Detail.vue
+++ b/front/src/views/radios/Detail.vue
@@ -24,15 +24,15 @@
           </router-link>
           <dangerous-button class="labeled icon" :action="deleteRadio">
             <i class="trash icon"></i> Delete
-            <p slot="modal-header"><translate :translate-params="{radio: radio.name}">Do you want to delete the radio "%{ radio }"?</translate></p>
-            <p slot="modal-content"><translate>This will completely delete this radio and cannot be undone.</translate></p>
-            <p slot="modal-confirm"><translate>Delete radio</translate></p>
+            <p slot="modal-header"><translate :translate-context="'Popup/Radio/Title'" :translate-params="{radio: radio.name}">Do you want to delete the radio "%{ radio }"?</translate></p>
+            <p slot="modal-content"><translate :translate-context="'Popup/Radio/Paragraph'">This will completely delete this radio and cannot be undone.</translate></p>
+            <p slot="modal-confirm"><translate :translate-context="'Popup/Radio/Button.Label/Verb'">Delete radio</translate></p>
           </dangerous-button>
         </template>
       </div>
     </section>
     <section class="ui vertical stripe segment">
-      <h2><translate>Tracks</translate></h2>
+      <h2><translate :translate-context="'Content/*/*'">Tracks</translate></h2>
       <track-table :tracks="tracks"></track-table>
       <div class="ui center aligned basic segment">
         <pagination
@@ -77,7 +77,7 @@ export default {
   computed: {
     labels() {
       return {
-        title: this.$gettext("Radio")
+        title: this.$pgettext('Head/Radio/Title', "Radio")
       }
     }
   },