Merge pull request #1347 from ZogStriP/change-your-avatar-in-a-modal
change your avatar in a modal
This commit is contained in:
commit
b6e66372d4
|
@ -0,0 +1,46 @@
|
||||||
|
/**
|
||||||
|
The modal for selecting an avatar
|
||||||
|
|
||||||
|
@class AvatarSelectorController
|
||||||
|
@extends Discourse.Controller
|
||||||
|
@namespace Discourse
|
||||||
|
@uses Discourse.ModalFunctionality
|
||||||
|
@module Discourse
|
||||||
|
**/
|
||||||
|
Discourse.AvatarSelectorController = Discourse.Controller.extend(Discourse.ModalFunctionality, {
|
||||||
|
init: function() {
|
||||||
|
// copy some data to support the cancel action
|
||||||
|
this.setProperties(this.get("currentUser").getProperties(
|
||||||
|
"username",
|
||||||
|
"has_uploaded_avatar",
|
||||||
|
"use_uploaded_avatar",
|
||||||
|
"gravatar_template",
|
||||||
|
"uploaded_avatar_template"
|
||||||
|
));
|
||||||
|
},
|
||||||
|
|
||||||
|
toggleUseUploadedAvatar: function(toggle) {
|
||||||
|
this.set("use_uploaded_avatar", toggle);
|
||||||
|
},
|
||||||
|
|
||||||
|
saveAvatarSelection: function() {
|
||||||
|
// sends the information to the server if it has changed
|
||||||
|
if (this.get("use_uploaded_avatar") !== this.get("currentUser.use_uploaded_avatar")) {
|
||||||
|
var data = { use_uploaded_avatar: this.get("use_uploaded_avatar") };
|
||||||
|
Discourse.ajax("/users/" + this.get("currentUser.username") + "/preferences/avatar/toggle", { type: 'PUT', data: data });
|
||||||
|
}
|
||||||
|
// saves the data back to the currentUser object
|
||||||
|
var currentUser = this.get("currentUser");
|
||||||
|
currentUser.setProperties(this.getProperties(
|
||||||
|
"has_uploaded_avatar",
|
||||||
|
"use_uploaded_avatar",
|
||||||
|
"gravatar_template",
|
||||||
|
"uploaded_avatar_template"
|
||||||
|
));
|
||||||
|
if (this.get("use_uploaded_avatar")) {
|
||||||
|
currentUser.set("avatar_template", this.get("uploaded_avatar_template"));
|
||||||
|
} else {
|
||||||
|
currentUser.set("avatar_template", this.get("gravatar_template"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
|
@ -1,84 +0,0 @@
|
||||||
/**
|
|
||||||
This controller supports actions related to updating one's avatar
|
|
||||||
|
|
||||||
@class PreferencesAvatarController
|
|
||||||
@extends Discourse.ObjectController
|
|
||||||
@namespace Discourse
|
|
||||||
@module Discourse
|
|
||||||
**/
|
|
||||||
Discourse.PreferencesAvatarController = Discourse.ObjectController.extend({
|
|
||||||
uploading: false,
|
|
||||||
uploadProgress: 0,
|
|
||||||
uploadDisabled: Em.computed.or("uploading"),
|
|
||||||
useGravatar: Em.computed.not("use_uploaded_avatar"),
|
|
||||||
useUploadedAvatar: Em.computed.alias("use_uploaded_avatar"),
|
|
||||||
|
|
||||||
toggleUseUploadedAvatar: function(toggle) {
|
|
||||||
if (this.get("use_uploaded_avatar") !== toggle) {
|
|
||||||
var controller = this;
|
|
||||||
this.set("use_uploaded_avatar", toggle);
|
|
||||||
Discourse.ajax("/users/" + this.get("username") + "/preferences/avatar/toggle", { type: 'PUT', data: { use_uploaded_avatar: toggle }})
|
|
||||||
.then(function(result) { controller.set("avatar_template", result.avatar_template); });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
uploadButtonText: function() {
|
|
||||||
return this.get("uploading") ? I18n.t("user.change_avatar.uploading") : I18n.t("user.change_avatar.upload");
|
|
||||||
}.property("uploading"),
|
|
||||||
|
|
||||||
uploadAvatar: function() {
|
|
||||||
var controller = this;
|
|
||||||
var $upload = $("#avatar-input");
|
|
||||||
|
|
||||||
// do nothing if no file is selected
|
|
||||||
if (Em.isEmpty($upload.val())) { return; }
|
|
||||||
|
|
||||||
this.set("uploading", true);
|
|
||||||
|
|
||||||
// define the upload endpoint
|
|
||||||
$upload.fileupload({
|
|
||||||
url: Discourse.getURL("/users/" + this.get("username") + "/preferences/avatar"),
|
|
||||||
dataType: "json",
|
|
||||||
timeout: 20000
|
|
||||||
});
|
|
||||||
|
|
||||||
// when there is a progression for the upload
|
|
||||||
$upload.on("fileuploadprogressall", function (e, data) {
|
|
||||||
var progress = parseInt(data.loaded / data.total * 100, 10);
|
|
||||||
controller.set("uploadProgress", progress);
|
|
||||||
});
|
|
||||||
|
|
||||||
// when the upload is successful
|
|
||||||
$upload.on("fileuploaddone", function (e, data) {
|
|
||||||
// set some properties
|
|
||||||
controller.setProperties({
|
|
||||||
has_uploaded_avatar: true,
|
|
||||||
use_uploaded_avatar: true,
|
|
||||||
avatar_template: data.result.url,
|
|
||||||
uploaded_avatar_template: data.result.url
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// when there has been an error with the upload
|
|
||||||
$upload.on("fileuploadfail", function (e, data) {
|
|
||||||
Discourse.Utilities.displayErrorForUpload(data);
|
|
||||||
});
|
|
||||||
|
|
||||||
// when the upload is done
|
|
||||||
$upload.on("fileuploadalways", function (e, data) {
|
|
||||||
// prevent automatic upload when selecting a file
|
|
||||||
$upload.fileupload("destroy");
|
|
||||||
$upload.off();
|
|
||||||
// clear file input
|
|
||||||
$upload.val("");
|
|
||||||
// indicate upload is done
|
|
||||||
controller.setProperties({
|
|
||||||
uploading: false,
|
|
||||||
uploadProgress: 0
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// *actually* launch the upload
|
|
||||||
$("#avatar-input").fileupload("add", { fileInput: $("#avatar-input") });
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -171,24 +171,9 @@ Handlebars.registerHelper('avatar', function(user, options) {
|
||||||
Ember.Handlebars.registerBoundHelper('boundAvatar', function(user, options) {
|
Ember.Handlebars.registerBoundHelper('boundAvatar', function(user, options) {
|
||||||
return new Handlebars.SafeString(Discourse.Utilities.avatarImg({
|
return new Handlebars.SafeString(Discourse.Utilities.avatarImg({
|
||||||
size: options.hash.imageSize,
|
size: options.hash.imageSize,
|
||||||
avatarTemplate: Em.get(user, 'avatar_template')
|
avatarTemplate: Em.get(user, options.hash.template || 'avatar_template')
|
||||||
}));
|
}));
|
||||||
}, 'avatar_template');
|
}, 'avatar_template', 'uploaded_avatar_template', 'gravatar_template');
|
||||||
|
|
||||||
/**
|
|
||||||
Bound avatar helper.
|
|
||||||
Will rerender whenever the "uploaded_avatar_template" changes.
|
|
||||||
Only available for the current user.
|
|
||||||
|
|
||||||
@method boundUploadedAvatar
|
|
||||||
@for Handlebars
|
|
||||||
**/
|
|
||||||
Ember.Handlebars.registerBoundHelper('boundUploadedAvatar', function(user, options) {
|
|
||||||
return new Handlebars.SafeString(Discourse.Utilities.avatarImg({
|
|
||||||
size: options.hash.imageSize,
|
|
||||||
avatarTemplate: Em.get(user, 'uploaded_avatar_template')
|
|
||||||
}));
|
|
||||||
}, 'uploaded_avatar_template');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Nicely format a date without a binding since the date doesn't need to change.
|
Nicely format a date without a binding since the date doesn't need to change.
|
||||||
|
|
|
@ -13,6 +13,13 @@ Discourse.PreferencesRoute = Discourse.RestrictedUserRoute.extend({
|
||||||
|
|
||||||
renderTemplate: function() {
|
renderTemplate: function() {
|
||||||
this.render('preferences', { into: 'user', outlet: 'userOutlet', controller: 'preferences' });
|
this.render('preferences', { into: 'user', outlet: 'userOutlet', controller: 'preferences' });
|
||||||
|
},
|
||||||
|
|
||||||
|
events: {
|
||||||
|
showAvatarSelector: function() {
|
||||||
|
Discourse.Route.showModal(this, 'avatarSelector');
|
||||||
|
this.controllerFor("avatarSelector").init();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -117,32 +124,3 @@ Discourse.PreferencesUsernameRoute = Discourse.RestrictedUserRoute.extend({
|
||||||
controller.setProperties({ model: user, newUsername: user.get('username') });
|
controller.setProperties({ model: user, newUsername: user.get('username') });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
The route for updating a user's avatar
|
|
||||||
|
|
||||||
@class PreferencesAvatarRoute
|
|
||||||
@extends Discourse.RestrictedUserRoute
|
|
||||||
@namespace Discourse
|
|
||||||
@module Discourse
|
|
||||||
**/
|
|
||||||
Discourse.PreferencesAvatarRoute = Discourse.RestrictedUserRoute.extend({
|
|
||||||
model: function() {
|
|
||||||
return this.modelFor('user');
|
|
||||||
},
|
|
||||||
|
|
||||||
renderTemplate: function() {
|
|
||||||
return this.render({ into: 'user', outlet: 'userOutlet' });
|
|
||||||
},
|
|
||||||
|
|
||||||
// A bit odd, but if we leave to /preferences we need to re-render that outlet
|
|
||||||
exit: function() {
|
|
||||||
this._super();
|
|
||||||
this.render('preferences', { into: 'user', outlet: 'userOutlet', controller: 'preferences' });
|
|
||||||
},
|
|
||||||
|
|
||||||
setupController: function(controller, user) {
|
|
||||||
controller.setProperties({ model: user });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
|
@ -5,6 +5,6 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button class='btn btn-primary' {{action saveAutoClose}} data-dismiss="modal">{{i18n topic.auto_close_save}}</button>
|
<button class='btn btn-primary' {{action saveAutoClose}} data-dismiss="modal">{{i18n topic.auto_close_save}}</button>
|
||||||
<button class='btn' data-dismiss="modal">{{i18n topic.auto_close_cancel}}</button>
|
<a data-dismiss="modal">{{i18n topic.auto_close_cancel}}</a>
|
||||||
<button class='btn pull-right' {{action removeAutoClose}} data-dismiss="modal">{{i18n topic.auto_close_remove}}</button>
|
<button class='btn pull-right' {{action removeAutoClose}} data-dismiss="modal">{{i18n topic.auto_close_remove}}</button>
|
||||||
</div>
|
</div>
|
|
@ -0,0 +1,29 @@
|
||||||
|
<div class="modal-body">
|
||||||
|
<div>
|
||||||
|
<input type="radio" id="avatar" name="avatar" value="gravatar" {{action toggleUseUploadedAvatar false}}>
|
||||||
|
<label class="radio" for="avatar">{{avatar controller imageSize="large" template="gravatar_template"}} {{{i18n user.change_avatar.gravatar}}} {{currentUser.email}}</label>
|
||||||
|
<a href="//gravatar.com/emails" target="_blank" title="{{i18n user.change_avatar.gravatar_title}}" class="btn"><i class="icon-pencil"></i></a>
|
||||||
|
<div>
|
||||||
|
<input type="radio" id="uploaded_avatar" name="avatar" value="uploaded_avatar" {{action toggleUseUploadedAvatar true}} {{bindAttr disabled="view.uploadedAvatarDisabled" }}>
|
||||||
|
<label class="radio" for="uploaded_avatar">
|
||||||
|
{{#if has_uploaded_avatar}}
|
||||||
|
{{boundAvatar controller imageSize="large" template="uploaded_avatar_template"}} {{i18n user.change_avatar.uploaded_avatar}}
|
||||||
|
{{else}}
|
||||||
|
{{i18n user.change_avatar.uploaded_avatar_empty}}
|
||||||
|
{{/if}}
|
||||||
|
</label>
|
||||||
|
<button id="fake-avatar-input" class="btn" {{bindAttr disabled="view.uploading"}} title="{{i18n user.change_avatar.upload_title}}">
|
||||||
|
<i class="icon-picture"></i> {{view.uploadButtonText}}
|
||||||
|
</button>
|
||||||
|
<input type="file" id="avatar-input" accept="image/*" style="display:none">
|
||||||
|
{{#if view.uploading}}
|
||||||
|
<span>{{i18n upload_selector.uploading}} {{view.uploadProgress}}%</span>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button class="btn btn-primary" {{action saveAvatarSelection}} data-dismiss="modal">{{i18n save}}</button>
|
||||||
|
<a data-dismiss="modal">{{i18n cancel}}</a>
|
||||||
|
</div>
|
|
@ -1,39 +0,0 @@
|
||||||
<form class="form-horizontal">
|
|
||||||
|
|
||||||
<div class="control-group">
|
|
||||||
<div class="controls">
|
|
||||||
<h3>{{i18n user.change_avatar.title}}</h3>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="control-group">
|
|
||||||
<label class="control-label">{{i18n user.avatar.title}}</label>
|
|
||||||
<div class="controls">
|
|
||||||
<label class="radio">
|
|
||||||
<input type="radio" name="avatar" value="gravatar" {{action toggleUseUploadedAvatar false}}> {{avatar this imageSize="large" template="gravatar_template"}} {{i18n user.change_avatar.gravatar}} <a href="//gravatar.com/emails/" target="_blank" class="btn pad-left" title="{{i18n user.change_avatar.gravatar_title}}">{{i18n user.change}}</a>
|
|
||||||
</label>
|
|
||||||
{{#if has_uploaded_avatar}}
|
|
||||||
<label class="radio">
|
|
||||||
<input type="radio" name="avatar" value="uploaded_avatar" {{action toggleUseUploadedAvatar true}}> {{boundUploadedAvatar this imageSize="large"}} {{i18n user.change_avatar.uploaded_avatar}}
|
|
||||||
</label>
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="control-group">
|
|
||||||
<div class="instructions">{{i18n user.change_avatar.upload_instructions}}</div>
|
|
||||||
<div class="controls">
|
|
||||||
<div>
|
|
||||||
<input type="file" id="avatar-input" accept="image/*">
|
|
||||||
</div>
|
|
||||||
<button {{action uploadAvatar}} {{bindAttr disabled="uploadDisabled"}} class="btn btn-primary">
|
|
||||||
<span class="add-upload"><i class="icon-picture"></i><i class="icon-plus"></i></span>
|
|
||||||
{{uploadButtonText}}
|
|
||||||
</button>
|
|
||||||
{{#if uploading}}
|
|
||||||
<span>{{i18n upload_selector.uploading}} {{uploadProgress}}%</span>
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</form>
|
|
|
@ -44,7 +44,8 @@
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label class="control-label">{{i18n user.avatar.title}}</label>
|
<label class="control-label">{{i18n user.avatar.title}}</label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
{{avatar model imageSize="large"}}
|
{{boundAvatar model imageSize="large"}}
|
||||||
|
<button {{action showAvatarSelector}} class="btn pad-left">{{i18n user.change}}</button>
|
||||||
</div>
|
</div>
|
||||||
<div class='instructions'>
|
<div class='instructions'>
|
||||||
{{#if Discourse.SiteSettings.allow_uploaded_avatars}}
|
{{#if Discourse.SiteSettings.allow_uploaded_avatars}}
|
||||||
|
@ -53,7 +54,6 @@
|
||||||
{{else}}
|
{{else}}
|
||||||
{{{i18n user.avatar.instructions.gravatar}}} {{email}}
|
{{{i18n user.avatar.instructions.gravatar}}} {{email}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#linkTo "preferences.avatar" class="btn pad-left"}}{{i18n user.change}}{{/linkTo}}
|
|
||||||
{{else}}
|
{{else}}
|
||||||
{{{i18n user.avatar.instructions.gravatar}}} {{email}}
|
{{{i18n user.avatar.instructions.gravatar}}} {{email}}
|
||||||
<a href="//gravatar.com/emails/" target="_blank" title="{{i18n user.change_avatar.gravatar_title}}" class="btn pad-left">{{i18n user.change}}</a>
|
<a href="//gravatar.com/emails/" target="_blank" title="{{i18n user.change_avatar.gravatar_title}}" class="btn pad-left">{{i18n user.change}}</a>
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
/**
|
||||||
|
This view handles the avatar selection interface
|
||||||
|
|
||||||
|
@class AvatarSelectorView
|
||||||
|
@extends Discourse.ModalBodyView
|
||||||
|
@namespace Discourse
|
||||||
|
@module Discourse
|
||||||
|
**/
|
||||||
|
Discourse.AvatarSelectorView = Discourse.ModalBodyView.extend({
|
||||||
|
templateName: 'modal/avatar_selector',
|
||||||
|
classNames: ['avatar-selector'],
|
||||||
|
title: I18n.t('user.change_avatar.title'),
|
||||||
|
uploading: false,
|
||||||
|
uploadProgress: 0,
|
||||||
|
uploadedAvatarDisabled: Em.computed.not("controller.has_uploaded_avatar"),
|
||||||
|
|
||||||
|
didInsertElement: function() {
|
||||||
|
var view = this;
|
||||||
|
var $upload = $("#avatar-input");
|
||||||
|
|
||||||
|
this._super();
|
||||||
|
|
||||||
|
// simulate a click on the hidden file input when clicking on our fake file input
|
||||||
|
$("#fake-avatar-input").on("click", function(e) {
|
||||||
|
// do *NOT* use the cached `$upload` variable, because fileupload is cloning & replacing the input
|
||||||
|
// cf. https://github.com/blueimp/jQuery-File-Upload/wiki/Frequently-Asked-Questions#why-is-the-file-input-field-cloned-and-replaced-after-each-selection
|
||||||
|
$("#avatar-input").click();
|
||||||
|
e.preventDefault();
|
||||||
|
});
|
||||||
|
|
||||||
|
// define the upload endpoint
|
||||||
|
$upload.fileupload({
|
||||||
|
url: Discourse.getURL("/users/" + this.get("controller.username") + "/preferences/avatar"),
|
||||||
|
dataType: "json",
|
||||||
|
timeout: 20000,
|
||||||
|
fileInput: $upload
|
||||||
|
});
|
||||||
|
|
||||||
|
// when a file has been selected
|
||||||
|
$upload.on("fileuploadadd", function (e, data) {
|
||||||
|
view.set("uploading", true);
|
||||||
|
});
|
||||||
|
|
||||||
|
// when there is a progression for the upload
|
||||||
|
$upload.on("fileuploadprogressall", function (e, data) {
|
||||||
|
var progress = parseInt(data.loaded / data.total * 100, 10);
|
||||||
|
view.set("uploadProgress", progress);
|
||||||
|
});
|
||||||
|
|
||||||
|
// when the upload is successful
|
||||||
|
$upload.on("fileuploaddone", function (e, data) {
|
||||||
|
// set some properties
|
||||||
|
view.get("controller").setProperties({
|
||||||
|
has_uploaded_avatar: true,
|
||||||
|
use_uploaded_avatar: true,
|
||||||
|
uploaded_avatar_template: data.result.url
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// when there has been an error with the upload
|
||||||
|
$upload.on("fileuploadfail", function (e, data) {
|
||||||
|
Discourse.Utilities.displayErrorForUpload(data);
|
||||||
|
});
|
||||||
|
|
||||||
|
// when the upload is done
|
||||||
|
$upload.on("fileuploadalways", function (e, data) {
|
||||||
|
view.setProperties({ uploading: false, uploadProgress: 0 });
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
willDestroyElement: function() {
|
||||||
|
$("#fake-avatar-input").off("click");
|
||||||
|
$("#avatar-input").fileupload("destroy");
|
||||||
|
},
|
||||||
|
|
||||||
|
// *HACK* used to select the proper radio button
|
||||||
|
selectedChanged: function() {
|
||||||
|
var view = this;
|
||||||
|
Em.run.next(function() {
|
||||||
|
var value = view.get('controller.use_uploaded_avatar') ? 'uploaded_avatar' : 'gravatar';
|
||||||
|
view.$('input:radio[name="avatar"]').val([value]);
|
||||||
|
});
|
||||||
|
}.observes('controller.use_uploaded_avatar'),
|
||||||
|
|
||||||
|
uploadButtonText: function() {
|
||||||
|
return this.get("uploading") ? I18n.t("uploading") : I18n.t("upload");
|
||||||
|
}.property("uploading")
|
||||||
|
|
||||||
|
});
|
|
@ -1,21 +0,0 @@
|
||||||
/**
|
|
||||||
This view handles rendering of a user's avatar uploader
|
|
||||||
|
|
||||||
@class PreferencesAvatarView
|
|
||||||
@extends Discourse.View
|
|
||||||
@namespace Discourse
|
|
||||||
@module Discourse
|
|
||||||
**/
|
|
||||||
Discourse.PreferencesAvatarView = Discourse.View.extend({
|
|
||||||
templateName: "user/avatar",
|
|
||||||
classNames: ["user-preferences"],
|
|
||||||
|
|
||||||
selectedChanged: function() {
|
|
||||||
var view = this;
|
|
||||||
Em.run.next(function() {
|
|
||||||
var value = view.get("controller.use_uploaded_avatar") ? "uploaded_avatar" : "gravatar";
|
|
||||||
view.$('input:radio[name="avatar"]').val([value]);
|
|
||||||
});
|
|
||||||
}.observes('controller.use_uploaded_avatar')
|
|
||||||
|
|
||||||
});
|
|
|
@ -323,3 +323,18 @@
|
||||||
width: 680px;
|
width: 680px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.avatar-selector {
|
||||||
|
label {
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
#avatar-input {
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.avatar {
|
||||||
|
margin: 5px 10px 5px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -376,7 +376,7 @@ class UsersController < ApplicationController
|
||||||
user.use_uploaded_avatar = params[:use_uploaded_avatar]
|
user.use_uploaded_avatar = params[:use_uploaded_avatar]
|
||||||
user.save!
|
user.save!
|
||||||
|
|
||||||
render json: { avatar_template: user.avatar_template }
|
render nothing: true
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -218,12 +218,11 @@ en:
|
||||||
|
|
||||||
change_avatar:
|
change_avatar:
|
||||||
title: "Change your avatar"
|
title: "Change your avatar"
|
||||||
upload_instructions: "Or you could upload an image"
|
gravatar: "<a href='//gravatar.com/emails' target='_blank'>Gravatar</a>, based on"
|
||||||
upload: "Upload a picture"
|
|
||||||
uploading: "Uploading the picture..."
|
|
||||||
gravatar: "Gravatar"
|
|
||||||
gravatar_title: "Change your avatar on Gravatar's website"
|
gravatar_title: "Change your avatar on Gravatar's website"
|
||||||
uploaded_avatar: "Uploaded picture"
|
uploaded_avatar: "Custom picture"
|
||||||
|
uploaded_avatar_empty: "Add a custom picture"
|
||||||
|
upload_title: "Upload your picture"
|
||||||
|
|
||||||
email:
|
email:
|
||||||
title: "Email"
|
title: "Email"
|
||||||
|
|
Loading…
Reference in New Issue