From 46bae31b3e702fc205f72629ea11fe9f2024a750 Mon Sep 17 00:00:00 2001
From: jovuit <jvuitton@disroot.org>
Date: Thu, 14 Feb 2019 10:28:12 +0100
Subject: [PATCH] #662: Resolve "Add contexts to translatable strings"

---
 CONTRIBUTING.rst                              |  1 +
 front/src/components/auth/Login.vue           | 22 ++++-----
 front/src/components/auth/Logout.vue          |  6 +--
 front/src/components/auth/Profile.vue         |  6 +--
 front/src/components/auth/Settings.vue        | 48 +++++++++----------
 .../src/components/auth/SubsonicTokenForm.vue | 34 ++++++-------
 6 files changed, 59 insertions(+), 58 deletions(-)

diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
index 63cc2d77..1d0fbf94 100644
--- a/CONTRIBUTING.rst
+++ b/CONTRIBUTING.rst
@@ -449,6 +449,7 @@ This hierarchical structure is made of several parts:
     - ``Moderation``
     - ``Player``
     - ``Playlist``
+    - ``Profile``
     - ``Favorites``
     - ``Notifications``
     - ``Radio``
diff --git a/front/src/components/auth/Login.vue b/front/src/components/auth/Login.vue
index 09a9c6c2..61be521b 100644
--- a/front/src/components/auth/Login.vue
+++ b/front/src/components/auth/Login.vue
@@ -2,20 +2,20 @@
   <main class="main pusher" v-title="labels.title">
     <section class="ui vertical stripe segment">
       <div class="ui small text container">
-        <h2><translate>Log in to your Funkwhale account</translate></h2>
+        <h2><translate :translate-context="'Content/Login/Title/Verb'">Log in to your Funkwhale account</translate></h2>
         <form class="ui form" @submit.prevent="submit()">
           <div v-if="error" class="ui negative message">
-            <div class="header"><translate>We cannot log you in</translate></div>
+            <div class="header"><translate :translate-context="'Content/Login/Error message.Title'">We cannot log you in</translate></div>
             <ul class="list">
-              <li v-if="error == 'invalid_credentials'"><translate>Please double-check your username/password couple is correct</translate></li>
-              <li v-else><translate>An unknown error happend, this can mean the server is down or cannot be reached</translate></li>
+              <li v-if="error == 'invalid_credentials'"><translate :translate-context="'Content/Login/Error message.List item/Call to action'">Please double-check your username/password couple is correct</translate></li>
+              <li v-else><translate :translate-context="'Content/Login/Error message/List item'">An unknown error happend, this can mean the server is down or cannot be reached</translate></li>
             </ul>
           </div>
           <div class="field">
             <label>
-              <translate>Username or email</translate> |
+              <translate :translate-context="'Content/Login/Input.Label/Noun'">Username or email</translate> |
               <router-link :to="{path: '/signup'}">
-                <translate>Create an account</translate>
+                <translate :translate-context="'Content/Login/Link/Verb'">Create an account</translate>
               </router-link>
             </label>
             <input
@@ -31,16 +31,16 @@
           </div>
           <div class="field">
             <label>
-              <translate>Password</translate> |
+              <translate :translate-context="'Content/Login/Input.Label'">Password</translate> |
               <router-link :to="{name: 'auth.password-reset', query: {email: credentials.username}}">
-                <translate>Reset your password</translate>
+                <translate :translate-context="'Content/Login/Link/Verb'">Reset your password</translate>
               </router-link>
             </label>
             <password-input :index="2" required v-model="credentials.password" />
 
           </div>
           <button tabindex="3" :class="['ui', {'loading': isLoading}, 'right', 'floated', 'green', 'button']" type="submit">
-             <translate>Login</translate>
+             <translate :translate-context="'Content/Login/Button.Label/Verb'">Login</translate>
           </button>
         </form>
       </div>
@@ -80,8 +80,8 @@ export default {
   },
   computed: {
     labels() {
-      let usernamePlaceholder = this.$gettext("Enter your username or email")
-      let title = this.$gettext("Log In")
+      let usernamePlaceholder = this.$pgettext('Content/Login/Input.Placeholder', "Enter your username or email")
+      let title = this.$pgettext('Head/Login/Title', "Log In")
       return {
         usernamePlaceholder,
         title
diff --git a/front/src/components/auth/Logout.vue b/front/src/components/auth/Logout.vue
index 90495f5e..3582d636 100644
--- a/front/src/components/auth/Logout.vue
+++ b/front/src/components/auth/Logout.vue
@@ -3,10 +3,10 @@
     <section class="ui vertical stripe segment">
       <div class="ui small text container">
         <h2>
-          <translate>Are you sure you want to log out?</translate>
+          <translate :translate-context="'Content/Login/Title'">Are you sure you want to log out?</translate>
         </h2>
         <p v-translate="{username: $store.state.auth.username}">You are currently logged in as %{ username }</p>
-        <button class="ui button" @click="$store.dispatch('auth/logout')"><translate>Yes, log me out!</translate></button>
+        <button class="ui button" @click="$store.dispatch('auth/logout')"><translate :translate-context="'Content/Login/Button.Label'">Yes, log me out!</translate></button>
       </div>
     </section>
   </main>
@@ -17,7 +17,7 @@ export default {
   computed: {
     labels() {
       return {
-        title: this.$gettext("Log Out")
+        title: this.$pgettext('Head/Login/Title', "Log Out")
       }
     }
   }
diff --git a/front/src/components/auth/Profile.vue b/front/src/components/auth/Profile.vue
index 73c9ab2d..1aaafd10 100644
--- a/front/src/components/auth/Profile.vue
+++ b/front/src/components/auth/Profile.vue
@@ -14,14 +14,14 @@
           </div>
         </h2>
         <div class="ui basic green label">
-          <translate>This is you!</translate>
+          <translate :translate-context="'Content/Profile/Button.Paragraph'">This is you!</translate>
         </div>
         <a v-if="profile.is_staff"
           class="ui yellow label"
           :href="$store.getters['instance/absoluteUrl']('/api/admin')"
           target="_blank">
           <i class="star icon"></i>
-          <translate>Staff member</translate>
+          <translate :translate-context="'Content/Profile/Button.Label'">Staff member</translate>
         </a>
       </div>
     </template>
@@ -43,7 +43,7 @@ export default {
       profile: state => state.auth.profile
     }),
     labels() {
-      let msg = this.$gettext("%{ username }'s profile")
+      let msg = this.$pgettext('Head/Profile/Title', "%{ username }'s profile")
       let usernameProfile = this.$gettextInterpolate(msg, {
         username: this.username
       })
diff --git a/front/src/components/auth/Settings.vue b/front/src/components/auth/Settings.vue
index 8305d0e0..7081e029 100644
--- a/front/src/components/auth/Settings.vue
+++ b/front/src/components/auth/Settings.vue
@@ -3,16 +3,16 @@
     <div class="ui vertical stripe segment">
       <section class="ui small text container">
         <h2 class="ui header">
-          <translate>Account settings</translate>
+          <translate :translate-context="'Content/Settings/Title'">Account settings</translate>
         </h2>
         <form class="ui form" @submit.prevent="submitSettings()">
           <div v-if="settings.success" class="ui positive message">
             <div class="header">
-              <translate>Settings updated</translate>
+              <translate :translate-context="'Content/Settings/Message'">Settings updated</translate>
             </div>
           </div>
           <div v-if="settings.errors.length > 0" class="ui negative message">
-            <div class="header"><translate>We cannot save your settings</translate></div>
+            <div class="header"><translate :translate-context="'Content/Settings/Error message.Title'">Your settings can't be updateds</translate></div>
             <ul class="list">
               <li v-for="error in settings.errors">{{ error }}</li>
             </ul>
@@ -25,38 +25,38 @@
             </select>
           </div>
           <button :class="['ui', {'loading': isLoading}, 'button']" type="submit">
-            <translate>Update settings</translate>
+            <translate :translate-context="'Content/Settings/Button.Label/Verb'">Update settings</translate>
           </button>
         </form>
       </section>
       <div class="ui hidden divider"></div>
       <section class="ui small text container">
         <h2 class="ui header">
-          <translate>Avatar</translate>
+          <translate :translate-context="'Content/Settings/Title'">Avatar</translate>
         </h2>
         <div class="ui form">
           <div v-if="avatarErrors.length > 0" class="ui negative message">
-            <div class="header"><translate>We cannot save your avatar</translate></div>
+            <div class="header"><translate :translate-context="'Content/Settings/Error message.Title'">Your avatar cannot be saved</translate></div>
             <ul class="list">
               <li v-for="error in avatarErrors">{{ error }}</li>
             </ul>
           </div>
           <div class="ui stackable grid">
             <div class="ui ten wide column">
-              <h3 class="ui header"><translate>Upload a new avatar</translate></h3>
-              <p><translate>PNG, GIF or JPG. At most 2MB. Will be downscaled to 400x400px.</translate></p>
+              <h3 class="ui header"><translate :translate-context="'Content/Settings/Title/Verb'">Upload a new avatar</translate></h3>
+              <p><translate :translate-context="'Content/Settings/Paragraph'">PNG, GIF or JPG. At most 2MB. Will be downscaled to 400x400px.</translate></p>
               <input class="ui input" ref="avatar" type="file" />
               <div class="ui hidden divider"></div>
               <button @click="submitAvatar" :class="['ui', {'loading': isLoadingAvatar}, 'button']">
-                <translate>Update avatar</translate>
+                <translate :translate-context="'Content/Settings/Button.Label/Verb'">Update avatar</translate>
               </button>
             </div>
             <div class="ui six wide column">
-              <h3 class="ui header"><translate>Current avatar</translate></h3>
+              <h3 class="ui header"><translate :translate-context="'Content/Settings/Title/Noun'">Current avatar</translate></h3>
               <img class="ui circular image" v-if="currentAvatar && currentAvatar.square_crop" v-lazy="$store.getters['instance/absoluteUrl'](currentAvatar.medium_square_crop)" />
               <div class="ui hidden divider"></div>
               <button @click="removeAvatar" v-if="currentAvatar && currentAvatar.square_crop" :class="['ui', {'loading': isLoadingAvatar}, ,'yellow', 'button']">
-                <translate>Remove avatar</translate>
+                <translate :translate-context="'Content/Settings/Button.Label/Verb'">Remove avatar</translate>
               </button>
             </div>
           </div>
@@ -65,43 +65,43 @@
       <div class="ui hidden divider"></div>
       <section class="ui small text container">
         <h2 class="ui header">
-          <translate>Change my password</translate>
+          <translate :translate-context="'Content/Settings/Title/Verb'">Change my password</translate>
         </h2>
         <div class="ui message">
-          <translate>Changing your password will also change your Subsonic API password if you have requested one.</translate>&nbsp;<translate>You will have to update your password on your clients that use this password.</translate>
+          <translate :translate-context="'Content/Settings/Paragraph'">Changing your password will also change your Subsonic API password if you have requested one.</translate>&nbsp;<translate :translate-context="'Content/Settings/Paragraph'">You will have to update your password on your clients that use this password.</translate>
         </div>
         <form class="ui form" @submit.prevent="submitPassword()">
           <div v-if="passwordError" class="ui negative message">
             <div class="header">
-              <translate>Cannot change your password</translate>
+              <translate :translate-context="'Content/Settings/Error message.Title'">Your password cannot be changed</translate>
             </div>
             <ul class="list">
-              <li v-if="passwordError == 'invalid_credentials'"><translate>Please double-check your password is correct</translate></li>
+              <li v-if="passwordError == 'invalid_credentials'"><translate :translate-context="'Content/Settings/Error message.List item/Call to action'">Please double-check your password is correct</translate></li>
             </ul>
           </div>
           <div class="field">
-            <label><translate>Old password</translate></label>
+            <label><translate :translate-context="'Content/Settings/Input.Label'">Old password</translate></label>
             <password-input required v-model="old_password" />
 
           </div>
           <div class="field">
-            <label><translate>New password</translate></label>
+            <label><translate :translate-context="'Content/Settings/Input.Label'">New password</translate></label>
             <password-input required v-model="new_password" />
           </div>
           <dangerous-button
             color="yellow"
             :class="['ui', {'loading': isLoading}, 'button']"
             :action="submitPassword">
-            <translate>Change password</translate>
-            <p slot="modal-header"><translate>Change your password?</translate></p>
+            <translate :translate-context="'Content/Settings/Button.Label'">Change password</translate>
+            <p slot="modal-header"><translate :translate-context="'Popup/Settings/Title'">Change your password?</translate></p>
             <div slot="modal-content">
-              <p><translate>Changing your password will have the following consequences</translate></p>
+              <p><translate :translate-context="'Popup/Settings/Paragraph'">Changing your password will have the following consequences:</translate></p>
               <ul>
-                <li><translate>You will be logged out from this session and have to log in with the new one</translate></li>
-                <li><translate>Your Subsonic password will be changed to a new, random one, logging you out from devices that used the old Subsonic password</translate></li>
+                <li><translate :translate-context="'Popup/Settings/List item'">You will be logged out from this session and have to log in with the new one</translate></li>
+                <li><translate :translate-context="'Popup/Settings/List item'">Your Subsonic password will be changed to a new, random one, logging you out from devices that used the old Subsonic password</translate></li>
               </ul>
             </div>
-            <p slot="modal-confirm"><translate>Disable access</translate></p>
+            <p slot="modal-confirm"><translate :translate-context="'Popup/Setting/Button.Label'">Disable access</translate></p>
           </dangerous-button>
         </form>
         <div class="ui hidden divider" />
@@ -260,7 +260,7 @@ export default {
   computed: {
     labels() {
       return {
-        title: this.$gettext("Account Settings")
+        title: this.$pgettext('Head/Settings/Title', "Account Settings")
       }
     },
     orderedSettingsFields() {
diff --git a/front/src/components/auth/SubsonicTokenForm.vue b/front/src/components/auth/SubsonicTokenForm.vue
index ac752d92..1e179dd9 100644
--- a/front/src/components/auth/SubsonicTokenForm.vue
+++ b/front/src/components/auth/SubsonicTokenForm.vue
@@ -1,23 +1,23 @@
 <template>
   <form class="ui form" @submit.prevent="requestNewToken()">
-    <h2><translate>Subsonic API password</translate></h2>
+    <h2><translate :translate-context="'Content/Settings/Title'">Subsonic API password</translate></h2>
     <p class="ui message" v-if="!subsonicEnabled">
-      <translate>The Subsonic API is not available on this Funkwhale instance.</translate>
+      <translate :translate-context="'Content/Settings/Paragraph'">The Subsonic API is not available on this Funkwhale instance.</translate>
     </p>
     <p>
-      <translate>Funkwhale is compatible with other music players that support the Subsonic API.</translate>&nbsp;<translate>You can use those to enjoy your playlist and music in offline mode, on your smartphone or tablet, for instance.</translate>
+      <translate :translate-context="'Content/Settings/Paragraph'">Funkwhale is compatible with other music players that support the Subsonic API.</translate>&nbsp;<translate :translate-context="'Content/Settings/Paragraph'">You can use those to enjoy your playlist and music in offline mode, on your smartphone or tablet, for instance.</translate>
     </p>
     <p>
-      <translate>However, accessing Funkwhale from those clients require a separate password you can set below.</translate>
+      <translate :translate-context="'Content/Settings/Paragraph'">However, accessing Funkwhale from those clients require a separate password you can set below.</translate>
     </p>
     <p><a href="https://docs.funkwhale.audio/users/apps.html#subsonic-compatible-clients" target="_blank">
-      <translate>Discover how to use Funkwhale from other apps</translate>
+      <translate :translate-context="'Content/Settings/Link'">Discover how to use Funkwhale from other apps</translate>
     </a></p>
     <div v-if="success" class="ui positive message">
       <div class="header">{{ successMessage }}</div>
     </div>
     <div v-if="subsonicEnabled && errors.length > 0" class="ui negative message">
-      <div class="header"><translate>Error</translate></div>
+      <div class="header"><translate :translate-context="'Content/Settings/Error message.Title'">Error</translate></div>
       <ul class="list">
         <li v-for="error in errors">{{ error }}</li>
       </ul>
@@ -31,25 +31,25 @@
         color="grey"
         :class="['ui', {'loading': isLoading}, 'button']"
         :action="requestNewToken">
-        <translate>Request a new password</translate>
-        <p slot="modal-header"><translate>Request a new Subsonic API password?</translate></p>
-        <p slot="modal-content"><translate>This will log you out from existing devices that use the current password.</translate></p>
-        <p slot="modal-confirm"><translate>Request a new password</translate></p>
+        <translate :translate-context="'Content/Settings/Button.Label/Verb'">Request a new password</translate>
+        <p slot="modal-header"><translate :translate-context="'Popup/Settings/Title'">Request a new Subsonic API password?</translate></p>
+        <p slot="modal-content"><translate :translate-context="'Popup/Settings/Paragraph'">This will log you out from existing devices that use the current password.</translate></p>
+        <p slot="modal-confirm"><translate :translate-context="'Popup/Settings/Button.Label/Verb'">Request a new password</translate></p>
       </dangerous-button>
       <button
         v-else
         color="grey"
         :class="['ui', {'loading': isLoading}, 'button']"
-        @click="requestNewToken"><translate>Request a password</translate></button>
+        @click="requestNewToken"><translate :translate-context="'Content/Settings/Button.Label/Verb'">Request a password</translate></button>
         <dangerous-button
           v-if="token"
           color="yellow"
           :class="['ui', {'loading': isLoading}, 'button']"
           :action="disable">
-          <translate>Disable Subsonic access</translate>
-          <p slot="modal-header"><translate>Disable Subsonic API access?</translate></p>
-          <p slot="modal-content"><translate>This will completely disable access to the Subsonic API using from account.</translate></p>
-          <p slot="modal-confirm"><translate>Disable access</translate></p>
+          <translate :translate-context="'Content/Settings/Button.Label/Verb'">Disable Subsonic access</translate>
+          <p slot="modal-header"><translate :translate-context="'Popup/Settings/Title'">Disable Subsonic API access?</translate></p>
+          <p slot="modal-content"><translate :translate-context="'Popup/Settings/Paragraph'">This will completely disable access to the Subsonic API using from account.</translate></p>
+          <p slot="modal-confirm"><translate :translate-context="'Popup/Settings/Button.Label'">Disable access</translate></p>
         </dangerous-button>
     </template>
   </form>
@@ -91,7 +91,7 @@ export default {
       })
     },
     requestNewToken () {
-      this.successMessage = this.$gettext('Password updated')
+      this.successMessage = this.$pgettext('Content/Settings/Message', 'Password updated')
       this.success = false
       this.errors = []
       this.isLoading = true
@@ -107,7 +107,7 @@ export default {
       })
     },
     disable () {
-      this.successMessage = this.$gettext('Access disabled')
+      this.successMessage = this.$pgettext('Content/Settings/Message', 'Access disabled')
       this.success = false
       this.errors = []
       this.isLoading = true
-- 
GitLab