diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 63cc2d771fc1e110f47be9722058fdf5e82e55dd..1d0fbf9407f8b691aff752f9101855b55b9503c5 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 09a9c6c29d5bb690b5c6eac3cbabd24883295b3d..61be521b5d24a5cab6f2c9226453fda48134cdf3 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 90495f5e0ed17fbb2485da7003a93d97a7bbf5a9..3582d6367411e9f7265b2dfbff203bd73482a797 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 73c9ab2d9c64950cd145c04cb70813a9e2671612..1aaafd102f845af3526621ae180692182555c83e 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 8305d0e05dd5b11553d842cc97b224261cf1859b..7081e0298df9536d4c9ef457acedc285d40d816d 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> <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> <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 ac752d92166778d7135916709f33d68ad80370b5..1e179dd95f215d316d32b1a3a77d9cd61ca0f786 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> <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> <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