Merge pull request #3 from VIVO-IFest/I18n

I18n - example cases and work from the Implementation Fest 2013
This commit is contained in:
Jim Blake 2013-05-01 14:47:01 -07:00
commit 25236f70e7
58 changed files with 1112 additions and 700 deletions

View file

@ -25,6 +25,8 @@ import edu.cornell.mannlib.vitro.webapp.dao.VClassDao;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
import edu.cornell.mannlib.vitro.webapp.dao.jena.ModelContext; import edu.cornell.mannlib.vitro.webapp.dao.jena.ModelContext;
import edu.cornell.mannlib.vitro.webapp.dao.jena.OntModelSelector; import edu.cornell.mannlib.vitro.webapp.dao.jena.OntModelSelector;
import edu.cornell.mannlib.vitro.webapp.i18n.I18n;
import edu.cornell.mannlib.vitro.webapp.i18n.I18nBundle;
/** /**
* A base class with some utility routines for page handler (created by * A base class with some utility routines for page handler (created by
@ -39,6 +41,7 @@ public abstract class AbstractPageHandler {
private static final Log log = LogFactory.getLog(AbstractPageHandler.class); private static final Log log = LogFactory.getLog(AbstractPageHandler.class);
protected final VitroRequest vreq; protected final VitroRequest vreq;
protected final I18nBundle i18n;
protected final ServletContext ctx; protected final ServletContext ctx;
protected final OntModel userAccountsModel; protected final OntModel userAccountsModel;
protected final OntModel unionModel; protected final OntModel unionModel;
@ -50,6 +53,7 @@ public abstract class AbstractPageHandler {
protected AbstractPageHandler(VitroRequest vreq) { protected AbstractPageHandler(VitroRequest vreq) {
this.vreq = vreq; this.vreq = vreq;
this.i18n = I18n.bundle(vreq);
this.ctx = vreq.getSession().getServletContext(); this.ctx = vreq.getSession().getServletContext();
OntModelSelector oms = ModelContext.getUnionOntModelSelector(ctx); OntModelSelector oms = ModelContext.getUnionOntModelSelector(ctx);
@ -154,7 +158,8 @@ public abstract class AbstractPageHandler {
private static final String ATTRIBUTE = Message.class.getName(); private static final String ATTRIBUTE = Message.class.getName();
public static void setMessage(HttpServletRequest req, Message message) { public static void setMessage(HttpServletRequest req, Message message) {
log.debug("Added message to session: " + message.getMessageInfoMap()); log.debug("Added message to session: "
+ message.getMessageInfoMap());
req.getSession().setAttribute(ATTRIBUTE, message); req.getSession().setAttribute(ATTRIBUTE, message);
} }

View file

@ -103,7 +103,7 @@ public abstract class UserAccountsAddPageStrategy extends UserAccountsPage {
FreemarkerEmailMessage email = FreemarkerEmailFactory FreemarkerEmailMessage email = FreemarkerEmailFactory
.createNewMessage(vreq); .createNewMessage(vreq);
email.addRecipient(TO, page.getAddedAccount().getEmailAddress()); email.addRecipient(TO, page.getAddedAccount().getEmailAddress());
email.setSubject("Your VIVO account has been created."); email.setSubject(i18n.text("account_created_subject", getSiteName()));
if (page.isExternalAuthOnly()) { if (page.isExternalAuthOnly()) {
email.setTemplate(EMAIL_TEMPLATE_NO_PASSWORD); email.setTemplate(EMAIL_TEMPLATE_NO_PASSWORD);
} else { } else {

View file

@ -2,6 +2,8 @@
package edu.cornell.mannlib.vitro.webapp.controller.accounts.admin; package edu.cornell.mannlib.vitro.webapp.controller.accounts.admin;
import static edu.cornell.mannlib.vitro.webapp.controller.accounts.user.UserAccountsUserController.getBogusStandardMessage;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
@ -15,7 +17,6 @@ import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.ManageRoot
import edu.cornell.mannlib.vitro.webapp.beans.UserAccount; import edu.cornell.mannlib.vitro.webapp.beans.UserAccount;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsPage; import edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsPage;
import edu.cornell.mannlib.vitro.webapp.controller.accounts.user.UserAccountsUserController;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
/** /**
@ -51,7 +52,7 @@ public class UserAccountsDeleter extends UserAccountsPage {
UserAccount loggedInAccount = LoginStatusBean.getCurrentUser(vreq); UserAccount loggedInAccount = LoginStatusBean.getCurrentUser(vreq);
if (loggedInAccount == null) { if (loggedInAccount == null) {
log.warn("Trying to delete accounts while not logged in!"); log.warn("Trying to delete accounts while not logged in!");
bogusMessage = UserAccountsUserController.BOGUS_STANDARD_MESSAGE; bogusMessage = getBogusStandardMessage(vreq);
return; return;
} }
@ -61,14 +62,14 @@ public class UserAccountsDeleter extends UserAccountsPage {
if (u == null) { if (u == null) {
log.warn("Delete account for '" + uri log.warn("Delete account for '" + uri
+ "' is bogus: no such user"); + "' is bogus: no such user");
bogusMessage = UserAccountsUserController.BOGUS_STANDARD_MESSAGE; bogusMessage = getBogusStandardMessage(vreq);
return; return;
} }
if (u.getUri().equals(loggedInAccount.getUri())) { if (u.getUri().equals(loggedInAccount.getUri())) {
log.warn("'" + u.getUri() log.warn("'" + u.getUri()
+ "' is trying to delete his own account."); + "' is trying to delete his own account.");
bogusMessage = UserAccountsUserController.BOGUS_STANDARD_MESSAGE; bogusMessage = getBogusStandardMessage(vreq);
return; return;
} }
@ -78,7 +79,7 @@ public class UserAccountsDeleter extends UserAccountsPage {
log.warn("Attempting to delete the root account, " log.warn("Attempting to delete the root account, "
+ "but not authorized. Logged in as " + "but not authorized. Logged in as "
+ LoginStatusBean.getCurrentUser(vreq)); + LoginStatusBean.getCurrentUser(vreq));
bogusMessage = UserAccountsUserController.BOGUS_STANDARD_MESSAGE; bogusMessage = getBogusStandardMessage(vreq);
return; return;
} }
} }

View file

@ -2,6 +2,8 @@
package edu.cornell.mannlib.vitro.webapp.controller.accounts.admin; package edu.cornell.mannlib.vitro.webapp.controller.accounts.admin;
import static edu.cornell.mannlib.vitro.webapp.controller.accounts.user.UserAccountsUserController.getBogusStandardMessage;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@ -20,7 +22,6 @@ import edu.cornell.mannlib.vitro.webapp.beans.SelfEditingConfiguration;
import edu.cornell.mannlib.vitro.webapp.beans.UserAccount; import edu.cornell.mannlib.vitro.webapp.beans.UserAccount;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsPage; import edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsPage;
import edu.cornell.mannlib.vitro.webapp.controller.accounts.user.UserAccountsUserController;
import edu.cornell.mannlib.vitro.webapp.controller.authenticate.Authenticator; import edu.cornell.mannlib.vitro.webapp.controller.authenticate.Authenticator;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
@ -116,7 +117,7 @@ public class UserAccountsEditPage extends UserAccountsPage {
if (userAccount == null) { if (userAccount == null) {
log.warn("Edit account for '" + userUri log.warn("Edit account for '" + userUri
+ "' is bogus: no such user"); + "' is bogus: no such user");
bogusMessage = UserAccountsUserController.BOGUS_STANDARD_MESSAGE; bogusMessage = getBogusStandardMessage(vreq);
return; return;
} }
if (userAccount.isRootUser()) { if (userAccount.isRootUser()) {
@ -125,7 +126,7 @@ public class UserAccountsEditPage extends UserAccountsPage {
log.warn("User is attempting to edit the root account, " log.warn("User is attempting to edit the root account, "
+ "but is not authorized to do so. Logged in as: " + "but is not authorized to do so. Logged in as: "
+ LoginStatusBean.getCurrentUser(vreq)); + LoginStatusBean.getCurrentUser(vreq));
bogusMessage = UserAccountsUserController.BOGUS_STANDARD_MESSAGE; bogusMessage = getBogusStandardMessage(vreq);
return; return;
} }
} }

View file

@ -46,14 +46,12 @@ public class UserAccountsCreatePasswordPage extends
@Override @Override
protected String alreadyLoggedInMessage(String currentUserEmail) { protected String alreadyLoggedInMessage(String currentUserEmail) {
return "You may not activate the account for " + userEmail return i18n.text("cant_activate_while_logged_in", userEmail, currentUserEmail);
+ " while you are logged in as " + currentUserEmail
+ ". Please log out and try again.";
} }
@Override @Override
protected String passwordChangeNotPendingMessage() { protected String passwordChangeNotPendingMessage() {
return "The account for " + userEmail + " has already been activated."; return i18n.text("account_already_activated", userEmail);
} }
@Override @Override
@ -69,7 +67,7 @@ public class UserAccountsCreatePasswordPage extends
FreemarkerEmailMessage email = FreemarkerEmailFactory FreemarkerEmailMessage email = FreemarkerEmailFactory
.createNewMessage(vreq); .createNewMessage(vreq);
email.addRecipient(TO, userAccount.getEmailAddress()); email.addRecipient(TO, userAccount.getEmailAddress());
email.setSubject("Password successfully created."); email.setSubject(i18n.text("password_created_subject", getSiteName()));
email.setTemplate(EMAIL_TEMPLATE); email.setTemplate(EMAIL_TEMPLATE);
email.setBodyMap(body); email.setBodyMap(body);
email.processTemplate(); email.processTemplate();

View file

@ -115,18 +115,17 @@ public class UserAccountsFirstTimeExternalPage extends UserAccountsPage {
private void validateExternalAuthId() { private void validateExternalAuthId() {
if (externalAuthId.isEmpty()) { if (externalAuthId.isEmpty()) {
bogusMessage = "Login failed - External ID is not found."; bogusMessage = i18n.text("external_id_not_provided");
return; return;
} }
if (null != userAccountsDao if (null != userAccountsDao
.getUserAccountByExternalAuthId(externalAuthId)) { .getUserAccountByExternalAuthId(externalAuthId)) {
bogusMessage = "User account already exists for '" + externalAuthId bogusMessage = i18n.text("external_id_already_in_use",
+ "'"; externalAuthId);
return; return;
} }
if (!Authenticator.getInstance(vreq).isUserPermittedToLogin(null)) { if (!Authenticator.getInstance(vreq).isUserPermittedToLogin(null)) {
bogusMessage = "User logins are temporarily disabled " bogusMessage = i18n.text("logins_disabled_for_maintenance");
+ "while the system is being maintained.";
return; return;
} }
} }

View file

@ -73,7 +73,7 @@ public abstract class UserAccountsFirstTimeExternalPageStrategy extends
FreemarkerEmailMessage email = FreemarkerEmailFactory FreemarkerEmailMessage email = FreemarkerEmailFactory
.createNewMessage(vreq); .createNewMessage(vreq);
email.addRecipient(TO, ua.getEmailAddress()); email.addRecipient(TO, ua.getEmailAddress());
email.setSubject("Your VIVO account has been created."); email.setSubject(i18n.text("account_created_subject", getSiteName()));
email.setTemplate(EMAIL_TEMPLATE); email.setTemplate(EMAIL_TEMPLATE);
email.setBodyMap(body); email.setBodyMap(body);
email.processTemplate(); email.processTemplate();

View file

@ -178,7 +178,7 @@ public abstract class UserAccountsMyAccountPageStrategy extends
FreemarkerEmailMessage email = FreemarkerEmailFactory FreemarkerEmailMessage email = FreemarkerEmailFactory
.createNewMessage(vreq); .createNewMessage(vreq);
email.addRecipient(TO, page.getUserAccount().getEmailAddress()); email.addRecipient(TO, page.getUserAccount().getEmailAddress());
email.setSubject("Your VIVO email account has been changed."); email.setSubject(i18n.text("email_changed_subject"));
email.setTemplate(EMAIL_TEMPLATE); email.setTemplate(EMAIL_TEMPLATE);
email.setBodyMap(body); email.setBodyMap(body);
email.processTemplate(); email.processTemplate();

View file

@ -23,8 +23,6 @@ public abstract class UserAccountsPasswordBasePage extends UserAccountsPage {
private static final Log log = LogFactory private static final Log log = LogFactory
.getLog(UserAccountsPasswordBasePage.class); .getLog(UserAccountsPasswordBasePage.class);
public static final String BOGUS_MESSAGE_NO_SUCH_ACCOUNT = "The account you are trying to set a password on is no longer available. Please contact your system administrator if you think this is an error.";
private static final String PARAMETER_SUBMIT = "submit"; private static final String PARAMETER_SUBMIT = "submit";
private static final String PARAMETER_USER = "user"; private static final String PARAMETER_USER = "user";
private static final String PARAMETER_KEY = "key"; private static final String PARAMETER_KEY = "key";
@ -79,7 +77,7 @@ public abstract class UserAccountsPasswordBasePage extends UserAccountsPage {
if (userAccount == null) { if (userAccount == null) {
log.warn("Password request for '" + userEmail log.warn("Password request for '" + userEmail
+ "' is bogus: no such user"); + "' is bogus: no such user");
bogusMessage = BOGUS_MESSAGE_NO_SUCH_ACCOUNT; bogusMessage = i18n.text("account_no_longer_exists");
return; return;
} }
@ -170,9 +168,9 @@ public abstract class UserAccountsPasswordBasePage extends UserAccountsPage {
public String getSuccessMessage() { public String getSuccessMessage() {
if (loggedIn) { if (loggedIn) {
return "Your password has been saved."; return i18n.text("password_saved");
} else { } else {
return "Your password has been saved. Please log in."; return i18n.text("password_saved_please_login");
} }
} }

View file

@ -46,14 +46,13 @@ public class UserAccountsResetPasswordPage extends UserAccountsPasswordBasePage
@Override @Override
protected String alreadyLoggedInMessage(String currentUserEmail) { protected String alreadyLoggedInMessage(String currentUserEmail) {
return "You may not reset the password for " + userEmail return i18n.text("cant_change_password_while_logged_in", userEmail,
+ " while you are logged in as " + currentUserEmail currentUserEmail);
+ ". Please log out and try again.";
} }
@Override @Override
protected String passwordChangeNotPendingMessage() { protected String passwordChangeNotPendingMessage() {
return "The password for " + userEmail + " has already been reset."; return i18n.text("password_change_not_pending", userEmail);
} }
@Override @Override
@ -69,7 +68,7 @@ public class UserAccountsResetPasswordPage extends UserAccountsPasswordBasePage
FreemarkerEmailMessage email = FreemarkerEmailFactory FreemarkerEmailMessage email = FreemarkerEmailFactory
.createNewMessage(vreq); .createNewMessage(vreq);
email.addRecipient(TO, userAccount.getEmailAddress()); email.addRecipient(TO, userAccount.getEmailAddress());
email.setSubject("Password changed."); email.setSubject(i18n.text("password_changed_subject"));
email.setTemplate(EMAIL_TEMPLATE); email.setTemplate(EMAIL_TEMPLATE);
email.setBodyMap(body); email.setBodyMap(body);
email.processTemplate(); email.processTemplate();

View file

@ -4,6 +4,8 @@ package edu.cornell.mannlib.vitro.webapp.controller.accounts.user;
import static edu.cornell.mannlib.vedit.beans.LoginStatusBean.AuthenticationSource.EXTERNAL; import static edu.cornell.mannlib.vedit.beans.LoginStatusBean.AuthenticationSource.EXTERNAL;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@ -18,6 +20,7 @@ import edu.cornell.mannlib.vitro.webapp.controller.authenticate.LoginRedirector;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerHttpServlet; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerHttpServlet;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.RedirectResponseValues; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.RedirectResponseValues;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
import edu.cornell.mannlib.vitro.webapp.i18n.I18n;
/** /**
* Parcel out the different actions required of the UserAccounts GUI. * Parcel out the different actions required of the UserAccounts GUI.
@ -26,8 +29,6 @@ public class UserAccountsUserController extends FreemarkerHttpServlet {
private static final Log log = LogFactory private static final Log log = LogFactory
.getLog(UserAccountsUserController.class); .getLog(UserAccountsUserController.class);
public static final String BOGUS_STANDARD_MESSAGE = "Request failed. Please contact your system administrator.";
private static final String ACTION_CREATE_PASSWORD = "/createPassword"; private static final String ACTION_CREATE_PASSWORD = "/createPassword";
private static final String ACTION_RESET_PASSWORD = "/resetPassword"; private static final String ACTION_RESET_PASSWORD = "/resetPassword";
private static final String ACTION_MY_ACCOUNT = "/myAccount"; private static final String ACTION_MY_ACCOUNT = "/myAccount";
@ -116,7 +117,7 @@ public class UserAccountsUserController extends FreemarkerHttpServlet {
return showLoginRedirection(vreq, page.getAfterLoginUrl()); return showLoginRedirection(vreq, page.getAfterLoginUrl());
} catch (LoginNotPermitted e) { } catch (LoginNotPermitted e) {
// This should have been anticipated by the page. // This should have been anticipated by the page.
return showHomePage(vreq, BOGUS_STANDARD_MESSAGE); return showHomePage(vreq, getBogusStandardMessage(vreq));
} }
} else { } else {
return page.showPage(); return page.showPage();
@ -124,7 +125,7 @@ public class UserAccountsUserController extends FreemarkerHttpServlet {
} }
private ResponseValues handleInvalidRequest(VitroRequest vreq) { private ResponseValues handleInvalidRequest(VitroRequest vreq) {
return showHomePage(vreq, BOGUS_STANDARD_MESSAGE); return showHomePage(vreq, getBogusStandardMessage(vreq));
} }
private ResponseValues showHomePage(VitroRequest vreq, String message) { private ResponseValues showHomePage(VitroRequest vreq, String message) {
@ -159,4 +160,8 @@ public class UserAccountsUserController extends FreemarkerHttpServlet {
} }
return uri; return uri;
} }
public static String getBogusStandardMessage(HttpServletRequest req) {
return I18n.bundle(req).text("request_failed");
}
} }

View file

@ -36,6 +36,7 @@ import edu.cornell.mannlib.vitro.webapp.filestorage.backend.FileStorageSetup;
import edu.cornell.mannlib.vitro.webapp.filestorage.model.FileInfo; import edu.cornell.mannlib.vitro.webapp.filestorage.model.FileInfo;
import edu.cornell.mannlib.vitro.webapp.filestorage.model.ImageInfo; import edu.cornell.mannlib.vitro.webapp.filestorage.model.ImageInfo;
import edu.cornell.mannlib.vitro.webapp.filestorage.uploadrequest.FileUploadServletRequest; import edu.cornell.mannlib.vitro.webapp.filestorage.uploadrequest.FileUploadServletRequest;
import edu.cornell.mannlib.vitro.webapp.i18n.I18n;
import edu.cornell.mannlib.vitro.webapp.web.images.PlaceholderUtil; import edu.cornell.mannlib.vitro.webapp.web.images.PlaceholderUtil;
/** /**
@ -48,6 +49,9 @@ public class ImageUploadController extends FreemarkerHttpServlet {
private static final String ATTRIBUTE_REFERRING_PAGE = "ImageUploadController.referringPage"; private static final String ATTRIBUTE_REFERRING_PAGE = "ImageUploadController.referringPage";
private static final String ERROR_CODE_UNRECOGNIZED_URI = "imageUpload.errorUnrecognizedURI";
private static final String ERROR_CODE_NO_URI = "imageUpload.errorNoURI";
/** Limit file size to 6 megabytes. */ /** Limit file size to 6 megabytes. */
public static final int MAXIMUM_FILE_SIZE = 6 * 1024 * 1024; public static final int MAXIMUM_FILE_SIZE = 6 * 1024 * 1024;
@ -97,6 +101,14 @@ public class ImageUploadController extends FreemarkerHttpServlet {
private static final String URL_HERE = UrlBuilder.getUrl("/uploadImages"); private static final String URL_HERE = UrlBuilder.getUrl("/uploadImages");
private static final String TEXT_BUNDLE = "imageUpload";
private static final String TEXT_STRING_UPLOAD_TITLE = "upload_page_title";
private static final String TEXT_STRING_UPLOAD_TITLE_WITH_NAME = "upload_page_title_with_name";
private static final String TEXT_STRING_REPLACE_TITLE = "replace_page_title";
private static final String TEXT_STRING_REPLACE_TITLE_WITH_NAME = "replace_page_title_with_name";
private static final String TEXT_STRING_CROP_TITLE = "crop_page_title";
private static final String TEXT_STRING_CROP_TITLE_WITH_NAME = "crop_page_title_with_name";
private FileStorage fileStorage; private FileStorage fileStorage;
/** /**
@ -218,7 +230,7 @@ public class ImageUploadController extends FreemarkerHttpServlet {
} }
} catch (UserMistakeException e) { } catch (UserMistakeException e) {
// Can't find the entity? Complain. // Can't find the entity? Complain.
return showAddImagePageWithError(vreq, null, e.getMessage()); return showAddImagePageWithError(vreq, null, e.formatMessage(vreq));
} catch (Exception e) { } catch (Exception e) {
// We weren't expecting this - log it, and apologize to the user. // We weren't expecting this - log it, and apologize to the user.
return new ExceptionResponseValues(e); return new ExceptionResponseValues(e);
@ -274,7 +286,7 @@ public class ImageUploadController extends FreemarkerHttpServlet {
return showCropImagePage(vreq, entity, return showCropImagePage(vreq, entity,
fileInfo.getBytestreamAliasUrl(), size); fileInfo.getBytestreamAliasUrl(), size);
} catch (UserMistakeException e) { } catch (UserMistakeException e) {
return showErrorMessage(vreq, entity, e.getMessage()); return showErrorMessage(vreq, entity, e.formatMessage(vreq));
} }
} }
@ -284,6 +296,7 @@ public class ImageUploadController extends FreemarkerHttpServlet {
*/ */
private ResponseValues showErrorMessage(VitroRequest vreq, private ResponseValues showErrorMessage(VitroRequest vreq,
Individual entity, String message) { Individual entity, String message) {
ImageInfo imageInfo = ImageInfo.instanceFromEntityUri( ImageInfo imageInfo = ImageInfo.instanceFromEntityUri(
vreq.getFullWebappDaoFactory(), entity); vreq.getFullWebappDaoFactory(), entity);
if (imageInfo == null) { if (imageInfo == null) {
@ -313,7 +326,7 @@ public class ImageUploadController extends FreemarkerHttpServlet {
return showExitPage(vreq, entity); return showExitPage(vreq, entity);
} catch (UserMistakeException e) { } catch (UserMistakeException e) {
return showErrorMessage(vreq, entity, e.getMessage()); return showErrorMessage(vreq, entity, e.formatMessage(vreq));
} }
} }
@ -350,15 +363,14 @@ public class ImageUploadController extends FreemarkerHttpServlet {
throws UserMistakeException { throws UserMistakeException {
String entityUri = vreq.getParameter(PARAMETER_ENTITY_URI); String entityUri = vreq.getParameter(PARAMETER_ENTITY_URI);
if (entityUri == null) { if (entityUri == null) {
throw new UserMistakeException("No entity URI was provided"); throw new UserMistakeException(ERROR_CODE_NO_URI);
} }
Individual entity = vreq.getFullWebappDaoFactory().getIndividualDao() Individual entity = vreq.getFullWebappDaoFactory().getIndividualDao()
.getIndividualByURI(entityUri); .getIndividualByURI(entityUri);
if (entity == null) { if (entity == null) {
throw new UserMistakeException( throw new UserMistakeException(ERROR_CODE_UNRECOGNIZED_URI,
"This URI is not recognized as belonging to anyone: '" entityUri);
+ entityUri + "'");
} }
return entity; return entity;
} }
@ -416,7 +428,7 @@ public class ImageUploadController extends FreemarkerHttpServlet {
rv.put(BODY_THUMBNAIL_URL, placeholderUrl); rv.put(BODY_THUMBNAIL_URL, placeholderUrl);
rv.put(BODY_FORM_ACTION, formAction); rv.put(BODY_FORM_ACTION, formAction);
rv.put(BODY_CANCEL_URL, cancelUrl); rv.put(BODY_CANCEL_URL, cancelUrl);
rv.put(BODY_TITLE, "Upload image" + forName(entity)); rv.put(BODY_TITLE, figureUploadPageTitle(vreq, entity));
rv.put(BODY_MAX_FILE_SIZE, MAXIMUM_FILE_SIZE / (1024 * 1024)); rv.put(BODY_MAX_FILE_SIZE, MAXIMUM_FILE_SIZE / (1024 * 1024));
rv.put(BODY_THUMBNAIL_HEIGHT, THUMBNAIL_HEIGHT); rv.put(BODY_THUMBNAIL_HEIGHT, THUMBNAIL_HEIGHT);
rv.put(BODY_THUMBNAIL_WIDTH, THUMBNAIL_WIDTH); rv.put(BODY_THUMBNAIL_WIDTH, THUMBNAIL_WIDTH);
@ -442,7 +454,7 @@ public class ImageUploadController extends FreemarkerHttpServlet {
rv.put(BODY_DELETE_URL, formAction(entity.getURI(), ACTION_DELETE_EDIT)); rv.put(BODY_DELETE_URL, formAction(entity.getURI(), ACTION_DELETE_EDIT));
rv.put(BODY_FORM_ACTION, formAction(entity.getURI(), ACTION_UPLOAD)); rv.put(BODY_FORM_ACTION, formAction(entity.getURI(), ACTION_UPLOAD));
rv.put(BODY_CANCEL_URL, exitPageUrl(vreq, entity.getURI())); rv.put(BODY_CANCEL_URL, exitPageUrl(vreq, entity.getURI()));
rv.put(BODY_TITLE, "Replace image" + forName(entity)); rv.put(BODY_TITLE, figureReplacePageTitle(vreq, entity));
rv.put(BODY_MAX_FILE_SIZE, MAXIMUM_FILE_SIZE / (1024 * 1024)); rv.put(BODY_MAX_FILE_SIZE, MAXIMUM_FILE_SIZE / (1024 * 1024));
rv.put(BODY_THUMBNAIL_HEIGHT, THUMBNAIL_HEIGHT); rv.put(BODY_THUMBNAIL_HEIGHT, THUMBNAIL_HEIGHT);
rv.put(BODY_THUMBNAIL_WIDTH, THUMBNAIL_WIDTH); rv.put(BODY_THUMBNAIL_WIDTH, THUMBNAIL_WIDTH);
@ -472,7 +484,7 @@ public class ImageUploadController extends FreemarkerHttpServlet {
rv.put(BODY_MAIN_IMAGE_WIDTH, dimensions.width); rv.put(BODY_MAIN_IMAGE_WIDTH, dimensions.width);
rv.put(BODY_FORM_ACTION, formAction(entity.getURI(), ACTION_SAVE)); rv.put(BODY_FORM_ACTION, formAction(entity.getURI(), ACTION_SAVE));
rv.put(BODY_CANCEL_URL, exitPageUrl(vreq, entity.getURI())); rv.put(BODY_CANCEL_URL, exitPageUrl(vreq, entity.getURI()));
rv.put(BODY_TITLE, "Crop Photo" + forName(entity)); rv.put(BODY_TITLE, figureCropPageTitle(vreq, entity));
return rv; return rv;
} }
@ -522,24 +534,59 @@ public class ImageUploadController extends FreemarkerHttpServlet {
} }
/** /**
* Format the entity's name for display as part of the page title. * Format the title for the Upload page.
*/ */
private String forName(Individual entity) { private String figureUploadPageTitle(HttpServletRequest req,
Individual entity) {
return figurePageTitle(req, entity, TEXT_STRING_UPLOAD_TITLE,
TEXT_STRING_UPLOAD_TITLE_WITH_NAME);
}
/**
* Format the title for the Replace page.
*/
private String figureReplacePageTitle(HttpServletRequest req,
Individual entity) {
return figurePageTitle(req, entity, TEXT_STRING_REPLACE_TITLE,
TEXT_STRING_REPLACE_TITLE_WITH_NAME);
}
/**
* Format the title for the Crop page.
*/
private String figureCropPageTitle(HttpServletRequest req, Individual entity) {
return figurePageTitle(req, entity, TEXT_STRING_CROP_TITLE,
TEXT_STRING_CROP_TITLE_WITH_NAME);
}
/**
* Format one of two page titles, depending on whether the entity has a
* name.
*/
private String figurePageTitle(HttpServletRequest req, Individual entity,
String noNameTitleKey, String nameTitleKey) {
if (entity != null) { if (entity != null) {
String name = entity.getName(); String name = entity.getName();
if (name != null) { if (name != null) {
return " for " + name; return I18n.text(req, TEXT_BUNDLE, nameTitleKey, name);
} }
} }
return ""; return I18n.text(req, TEXT_BUNDLE, noNameTitleKey);
} }
/** /**
* Holds an error message to use as a complaint to the user. * Holds an error message to use as a complaint to the user.
*/ */
static class UserMistakeException extends Exception { static class UserMistakeException extends Exception {
UserMistakeException(String message) { private final Object[] parameters;
UserMistakeException(String message, Object... parameters) {
super(message); super(message);
this.parameters = parameters;
}
public String formatMessage(HttpServletRequest req) {
return I18n.text(req, getMessage(), parameters);
} }
} }

View file

@ -49,6 +49,18 @@ import edu.cornell.mannlib.vitro.webapp.filestorage.uploadrequest.FileUploadServ
public class ImageUploadHelper { public class ImageUploadHelper {
private static final Log log = LogFactory.getLog(ImageUploadHelper.class); private static final Log log = LogFactory.getLog(ImageUploadHelper.class);
/*
* Keys to text strings for error messages.
*/
private static final String ERROR_CODE_NO_IMAGE_TO_CROP = "imageUpload.errorNoImageForCropping";
private static final String ERROR_CODE_IMAGE_TOO_SMALL = "imageUpload.errorImageTooSmall";
private static final String ERROR_CODE_UNKNOWN = "imageUpload.errorUnknown";
private static final String ERROR_CODE_FILE_TOO_BIG = "imageUpload.errorFileTooBig";
private static final String ERROR_CODE_UNRECOGNIZED_FILE_TYPE = "imageUpload.errorUnrecognizedFileType";
private static final String ERROR_CODE_NO_PHOTO_SELECTED = "imageUpload.errorNoPhotoSelected";
private static final String ERROR_CODE_BAD_MULTIPART_REQUEST = "imageUpload.errorBadMultipartRequest";
private static final String ERROR_CODE_FORM_FIELD_MISSING = "imageUpload.errorFormFieldMissing";
/** /**
* When they upload a new image, store it as this session attribute until * When they upload a new image, store it as this session attribute until
* we're ready to attach it to the Individual. * we're ready to attach it to the Individual.
@ -127,35 +139,31 @@ public class ImageUploadHelper {
Object exception = request.getAttribute(FILE_UPLOAD_EXCEPTION); Object exception = request.getAttribute(FILE_UPLOAD_EXCEPTION);
if (exception != null) { if (exception != null) {
int limit = MAXIMUM_FILE_SIZE / (1024 * 1024); int limit = MAXIMUM_FILE_SIZE / (1024 * 1024);
throw new UserMistakeException( throw new UserMistakeException(ERROR_CODE_FILE_TOO_BIG, limit);
"Please upload an image smaller than " + limit
+ " megabytes");
} }
Map<String, List<FileItem>> map = (Map<String, List<FileItem>>) request Map<String, List<FileItem>> map = (Map<String, List<FileItem>>) request
.getAttribute(FILE_ITEM_MAP); .getAttribute(FILE_ITEM_MAP);
if (map == null) { if (map == null) {
throw new IllegalStateException("Failed to parse the " throw new IllegalStateException(ERROR_CODE_BAD_MULTIPART_REQUEST);
+ "multi-part request for uploading an image.");
} }
List<FileItem> list = map.get(PARAMETER_UPLOADED_FILE); List<FileItem> list = map.get(PARAMETER_UPLOADED_FILE);
if ((list == null) || list.isEmpty()) { if ((list == null) || list.isEmpty()) {
throw new UserMistakeException("The form did not contain a '" throw new UserMistakeException(ERROR_CODE_FORM_FIELD_MISSING,
+ PARAMETER_UPLOADED_FILE + "' field."); PARAMETER_UPLOADED_FILE);
} }
FileItem file = list.get(0); FileItem file = list.get(0);
if (file.getSize() == 0) { if (file.getSize() == 0) {
throw new UserMistakeException("Please browse and select a photo."); throw new UserMistakeException(ERROR_CODE_NO_PHOTO_SELECTED);
} }
String filename = getSimpleFilename(file); String filename = getSimpleFilename(file);
String mimeType = getMimeType(file); String mimeType = getMimeType(file);
if (!RECOGNIZED_FILE_TYPES.containsValue(mimeType)) { if (!RECOGNIZED_FILE_TYPES.containsValue(mimeType)) {
log.debug("Unrecognized MIME type: '" + mimeType + "'"); log.debug("Unrecognized MIME type: '" + mimeType + "'");
throw new UserMistakeException("'" + filename throw new UserMistakeException(ERROR_CODE_UNRECOGNIZED_FILE_TYPE,
+ "' is not a recognized image file type. " filename);
+ "Please upload JPEG, GIF, or PNG files only.");
} }
return file; return file;
@ -221,10 +229,8 @@ public class ImageUploadHelper {
if ((size.height < THUMBNAIL_HEIGHT) if ((size.height < THUMBNAIL_HEIGHT)
|| (size.width < THUMBNAIL_WIDTH)) { || (size.width < THUMBNAIL_WIDTH)) {
throw new UserMistakeException( throw new UserMistakeException(ERROR_CODE_IMAGE_TOO_SMALL,
"The uploaded image should be at least " THUMBNAIL_HEIGHT, THUMBNAIL_WIDTH);
+ THUMBNAIL_HEIGHT + " pixels high and "
+ THUMBNAIL_WIDTH + " pixels wide.");
} }
return size; return size;
@ -237,8 +243,7 @@ public class ImageUploadHelper {
throw e; throw e;
} catch (Exception e) { } catch (Exception e) {
log.warn("Unexpected exception in image handling", e); log.warn("Unexpected exception in image handling", e);
throw new UserMistakeException("Sorry, we were unable to process " throw new UserMistakeException(ERROR_CODE_UNKNOWN);
+ "the photo you provided. Please try another photo.");
} finally { } finally {
if (source != null) { if (source != null) {
try { try {
@ -261,8 +266,7 @@ public class ImageUploadHelper {
ATTRIBUTE_TEMP_FILE); ATTRIBUTE_TEMP_FILE);
if (fileInfo == null) { if (fileInfo == null) {
throw new UserMistakeException( throw new UserMistakeException(ERROR_CODE_NO_IMAGE_TO_CROP);
"There is no image file to be cropped.");
} }
return fileInfo; return fileInfo;

View file

@ -61,8 +61,8 @@ public class FreemarkerEmailFactory {
FreemarkerEmailFactory factory = getFactory(vreq); FreemarkerEmailFactory factory = getFactory(vreq);
FreemarkerConfiguration fConfig = FreemarkerConfigurationLoader FreemarkerConfiguration fConfig = FreemarkerConfigurationLoader
.getConfig(vreq); .getConfig(vreq);
return new FreemarkerEmailMessage(fConfig, factory.getEmailSession(), return new FreemarkerEmailMessage(vreq, fConfig,
factory.getReplyToAddress()); factory.getEmailSession(), factory.getReplyToAddress());
} }
/** /**

View file

@ -27,8 +27,10 @@ import javax.mail.internet.MimeMultipart;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerConfiguration; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerConfiguration;
import edu.cornell.mannlib.vitro.webapp.web.directives.EmailDirective; import edu.cornell.mannlib.vitro.webapp.web.directives.EmailDirective;
import freemarker.core.Environment;
import freemarker.template.Template; import freemarker.template.Template;
import freemarker.template.TemplateException; import freemarker.template.TemplateException;
@ -47,7 +49,8 @@ public class FreemarkerEmailMessage {
private static final Log log = LogFactory private static final Log log = LogFactory
.getLog(FreemarkerEmailMessage.class); .getLog(FreemarkerEmailMessage.class);
private final Session session; private final VitroRequest vreq;
private final Session mailSession;
private final FreemarkerConfiguration config; private final FreemarkerConfiguration config;
private final List<Recipient> recipients = new ArrayList<Recipient>(); private final List<Recipient> recipients = new ArrayList<Recipient>();
@ -63,9 +66,10 @@ public class FreemarkerEmailMessage {
/** /**
* Package access - should only be created by the factory. * Package access - should only be created by the factory.
*/ */
FreemarkerEmailMessage(FreemarkerConfiguration fConfig, Session session, FreemarkerEmailMessage(VitroRequest vreq, FreemarkerConfiguration fConfig,
InternetAddress replyToAddress) { Session mailSession, InternetAddress replyToAddress) {
this.session = session; this.vreq = vreq;
this.mailSession = mailSession;
this.replyToAddress = replyToAddress; this.replyToAddress = replyToAddress;
this.config = fConfig; this.config = fConfig;
} }
@ -141,7 +145,13 @@ public class FreemarkerEmailMessage {
try { try {
Template template = config.getTemplate(templateName); Template template = config.getTemplate(templateName);
template.process(bodyMap, new StringWriter());
Environment env = template.createProcessingEnvironment(bodyMap,
new StringWriter());
env.setCustomAttribute("request", vreq);
env.setCustomAttribute("context", vreq.getSession()
.getServletContext());
env.process();
} catch (TemplateException e) { } catch (TemplateException e) {
log.error(e, e); log.error(e, e);
} catch (IOException e) { } catch (IOException e) {
@ -151,7 +161,7 @@ public class FreemarkerEmailMessage {
public boolean send() { public boolean send() {
try { try {
MimeMessage msg = new MimeMessage(session); MimeMessage msg = new MimeMessage(mailSession);
msg.setReplyTo(new Address[] { replyToAddress }); msg.setReplyTo(new Address[] { replyToAddress });
if (fromAddress == null) { if (fromAddress == null) {

View file

@ -40,7 +40,8 @@ public class I18nBundle {
this(bundleName, resources, MESSAGE_KEY_NOT_FOUND); this(bundleName, resources, MESSAGE_KEY_NOT_FOUND);
} }
private I18nBundle(String bundleName, ResourceBundle resources, String notFoundMessage) { private I18nBundle(String bundleName, ResourceBundle resources,
String notFoundMessage) {
if (bundleName == null) { if (bundleName == null) {
throw new IllegalArgumentException("bundleName may not be null"); throw new IllegalArgumentException("bundleName may not be null");
} }
@ -49,7 +50,8 @@ public class I18nBundle {
} }
if (resources == null) { if (resources == null) {
throw new NullPointerException("resources may not be null."); throw new NullPointerException("resources may not be null.");
}if (notFoundMessage == null) { }
if (notFoundMessage == null) {
throw new NullPointerException("notFoundMessage may not be null."); throw new NullPointerException("notFoundMessage may not be null.");
} }
this.bundleName = bundleName; this.bundleName = bundleName;
@ -58,11 +60,12 @@ public class I18nBundle {
} }
public String text(String key, Object... parameters) { public String text(String key, Object... parameters) {
log.debug("Asking for '" + key + "' from bundle '" + bundleName + "'");
String textString; String textString;
if (resources.containsKey(key)) { if (resources.containsKey(key)) {
textString = resources.getString(key); textString = resources.getString(key);
log.debug("In '" + bundleName + "', " + key + "='" + textString
+ "')");
return formatString(textString, parameters); return formatString(textString, parameters);
} else { } else {
String message = MessageFormat.format(notFoundMessage, bundleName, String message = MessageFormat.format(notFoundMessage, bundleName,

View file

@ -60,7 +60,7 @@ public class VitroResourceBundle extends ResourceBundle {
return new VitroResourceBundle(bundleName, ctx, appI18nPath, return new VitroResourceBundle(bundleName, ctx, appI18nPath,
themeI18nPath, control); themeI18nPath, control);
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
log.debug(e); log.info(e.getMessage());
return null; return null;
} catch (Exception e) { } catch (Exception e) {
log.warn(e, e); log.warn(e, e);

View file

@ -0,0 +1,218 @@
#
# Text strings for the controllers and templates
#
# Default (English)
#
save_changes = Save changes
cancel_link = Cancel
cancel_title = cancel
required_fields = required fields
or = or
alt_error_alert = Error alert icon
alt_confirmation = Confirmation icon
email_address = Email address
first_name = First name
last_name = Last name
roles = Roles
status = Status
ascending_order = ascending order
descending_order = descending order
select_one = Select one
type_more_characters = type more characters
no_match = no match
request_failed = Request failed. Please contact your system administrator.
#
# Image upload pages
#
upload_page_title = Upload image
upload_page_title_with_name = Upload image for {0}
upload_heading = Photo Upload
replace_page_title = Replace image
replace_page_title_with_name = Replace image for {0}
crop_page_title = Crop image
crop_page_title_with_name = Crop image for {0}
current_photo = Current Photo
upload_photo = Upload a photo
replace_photo = Replace Photo
photo_types = (JPEG, GIF or PNG)
maximum_file_size = Maximum file size: {0} megabytes
minimum_image_dimensions = Minimum image dimensions: {0} x {1} pixels
cropping_caption = Your profile photo will look like the image below.
cropping_note = To make adjustments, you can drag around and resize the photo to the right. \
When you are happy with your photo click the "Save Photo" button.
alt_thumbnail_photo = Individual photo
alt_image_to_crop = Image to be cropped
alt_preview_crop = Preview of photo cropped
delete_link = Delete photo
submit_upload = Upload photo
submit_save = Save photo
confirm_delete = Are you sure you want to delete this photo?
imageUpload.errorNoURI = No entity URI was provided
imageUpload.errorUnrecognizedURI = This URI is not recognized as belonging to anyone: ''{0}''
imageUpload.errorNoImageForCropping = There is no image file to be cropped.
imageUpload.errorImageTooSmall = The uploaded image should be at least {0} pixels high and {1} pixels wide.
imageUpload.errorUnknown = Sorry, we were unable to process the photo you provided. Please try another photo.
imageUpload.errorFileTooBig = Please upload an image smaller than {0} megabytes.
imageUpload.errorUnrecognizedFileType = ''{0}'' is not a recognized image file type. Please upload JPEG, GIF, or PNG files only.
imageUpload.errorNoPhotoSelected = Please browse and select a photo.
imageUpload.errorBadMultipartRequest = Failed to parse the multi-part request for uploading an image.
imageUpload.errorFormFieldMissing = The form did not contain a ''{0}'' field."
#
# User Accounts pages
#
account_management = Account Management
user_accounts_link = User accounts
user_accounts_title = user accounts
login_count = Login count
last_login = Last Login
add_new_account = Add new account
edit_account = Edit account
external_auth_only = Externally Authenticated Only
reset_password = Reset password
reset_password_note = Note: Instructions for resetting the password will \
be emailed to the address entered above. The password will not \
be reset until the user follows the link provided in this email.
new_password = New password
confirm_password = Confirm new password
minimum_password_length = Minimum of {0} characters in length.
leave_password_unchanged = Leaving this blank means that the password will not be changed.
confirm_initial_password = Confirm initial password
new_account_1 = A new account for
new_account_2 = was successfully created.
new_account_title = new account
new_account_notification = A notification email has been sent to {0} \
with instructions for activating the account and creating a password.
updated_account_1 = The account for
updated_account_2 = has been updated.
updated_account_title = updated account
updated_account_notification = A confirmation email has been sent to {0} \
with instructions for resetting a password. \
The password will not be reset until the user follows the link provided in this email.
deleted_accounts = Deleted {0} {0, choice, 0#accounts |1#account |1<accounts}.
enter_new_password = Please enter your new password for {0}
search_accounts_button = Search accounts
accounts_search_results = Search results for
select_account_to_delete = select this account to delete it
click_to_view_account = click to view account details
filter_by_roles = Filter by roles
view_all_accounts = View all accounts
view_all_accounts_title = view all accounts
new_account_note = Note: An email will be sent to the address entered above \
notifying that an account has been created. \
It will include instructions for activating the account and creating a password.
initial_password = Initial password
submit_add_new_account = Add new account
account_created = Your {0} account has been created.
account_created_subject Your {0} account has been created.
account_created_email_html = @@file files/accountCreatedEmail.html
account_created_email_text = @@file files/accountCreatedEmail.txt
account_created_external_email_html = @@file files/accountCreatedExternalOnlyEmail.html
account_created_external_email_text = @@file files/accountCreatedExternalOnlyEmail.txt
confirm_delete_account_singular = Are you sure you want to delete this account?
confirm_delete_account_plural = Are you sure you want to delete these accounts?
verify_this_match = verify this match
verify_this_match_title = verify this match
change_profile = change profile
change_profile_title = change profile
auth_matching_id_label = External Auth. ID / Matching ID
auth_id_label = External Authentication ID
auth_id_in_use = This Identifier is already in use.
auth_id_explanation = Can be used to associate the account with the user's profile via the matching property.
associated_profile_label = Associated profile:
select_associated_profile = Select the associated profile
create_associated_profile = Create the associated profile
email_changed_subject = Your {0} email account has been changed.
email_changed_html = @@file files/accountEmailChanged.html
email_changed_text = @@file files/accountEmailChanged.txt
create_your_password = Create your Password
password_created_subject = Your {0} password has successfully been created.
password_created_email_html = @@file files/passwordCreatedEmail.html
password_created_email_text = @@file files/passwordCreatedEmail.txt
password_reset_pending_subject = {0} reset password request
password_reset_pending_email_html = @@file files/passwordResetPending.html
password_reset_pending_email_text = @@file files/passwordResetPending.txt
password_reset_complete_subject = Your {0} password changed.
password_reset_complete_email_html = @@file files/passwordResetComplete.html
password_reset_complete_email_text = @@file files/passwordResetComplete.txt
reset_your_password = Reset your Password
first_time_login = First time log in
create_account = Create account
cant_activate_while_logged_in = You may not activate the account for {0} while you are logged in as {1}.
Please log out and try again.
account_already_activated = The account for {0} has already been activated.
cant_change_password_while_logged_in = You may not reset the password for {0} while you are logged in as {1}. \
Please log out and try again.
password_change_not_pending = The password for {0} has already been reset.
password_changed_subject = Password changed.
account_no_longer_exists = The account you are trying to set a password on is no longer available. \
Please contact your system administrator if you think this is an error.
password_saved = Your password has been saved.
password_saved_please_login = Your password has been saved. Please log in.
please_provide_contact_information = Please provide your contact information to finish creating your account.
first_time_login_note = Note: An email will be sent to the address entered above notifying \
that an account has been created.
first_time_external_email_html = @@file files/accountFirstTimeExternal.html
first_time_external_email_text = @@file files/accountFirstTimeExternal.txt
myAccount_heading = My account
myAccount_confirm_changes = Your changes have been saved.
myAccount_confirm_changes_plus_note = Your changes have been saved. A confirmation email has been sent to {0}.
email_change_will_be_confirmed = Note: if email changes, a confirmation email will be sent to the new email address entered above.
email_changed_subject = "Your VIVO email account has been changed.");
who_can_edit_profile = Who can edit my profile
add_profile_editor = Add profile editor
select_existing_last_name = Select an existing last name
selected_editors = Selected editors
remove_selection = Remove selection
remove_selection_title = remove selection
external_id_not_provided = Login failed - External ID is not found.
external_id_already_in_use = User account already exists for ''{0}''
logins_disabled_for_maintenance = User logins are temporarily disabled while the system is being maintained.
error_no_email = You must supply an email address.
error_email_already_exists = An account with that email address already exists.
error_invalid_email = ''{0}'' is not a valid email address.
error_external_auth_already_exists = An account with that external authorization ID already exists.
error_no_first_name = You must supply a first name.
error_no_last_name = You must supply a last name.
error_no_role = You must select a role.
error_no_password = No password supplied.
error_password_length = Password must be between {0} and {1} characters.
error_password_mismatch = Passwords do not match.

View file

@ -0,0 +1,43 @@
#
# Text strings for the controllers and templates
#
# Spanish
#
cancel_link = Cancelar
or = o
alt_error_alert = Icono de alerta con error
#
# Image upload pages
#
upload_page_title = Subir foto
upload_page_title_with_name = Subir imagen para {0}
upload_heading = Subir foto
replace_page_title = Reemplazar imagen
replace_page_title_with_name = Cambie la imagen por {0}
crop_page_title = Recortar imagen
crop_page_title_with_name = Recorte imagen para {0}
current_photo = Foto actual
upload_photo = Suba foto
replace_photo = Reemplace foto
photo_types = (JPEG, GIF, o PNG)
maximum_file_size = Tamaño máximo de archivo: {0} megabytes
minimum_image_dimensions = Dimensiones mínimas de imagen: {0} x {1} pixels
cropping_caption = La foto de tu perfil se verá como la imagen de abajo.
cropping_note = Para realizar ajustes, arrastre alrededor y cambie el tamaño de la foto de la derecha. \
Cuando esté satisfecho con su foto, haga clic en el botón "Guardar foto".
alt_thumbnail_photo = Foto de individuo
alt_image_to_crop = Imagen que desea recortar
alt_preview_crop = Vista previa de la foto recortada
delete_link = Borrar foto
submit_upload = Subir foto
submit_save = Guardar foto
confirm_delete = ¿Seguro que quiere borrar esta foto?

View file

@ -0,0 +1,39 @@
<html>
<head>
<title>{1}</title>
</head>
<body>
<p>
{2} {3}
</p>
<p>
<strong>Congratulations!</strong>
</p>
<p>
We have created your new account on {0}, associated with {4}.
</p>
<p>
If you did not request this new account you can safely ignore this email.
This request will expire if not acted upon for 30 days.
</p>
<p>
Click the link below to create your password for your new account using our secure server.
</p>
<p>
<a href="{5}" title="password">{5}</a>
</p>
<p>
If the link above doesn't work, you can copy and paste the link directly into your browser's address bar.
</p>
<p>
Thanks!
</p>
</body>
</html>

View file

@ -0,0 +1,17 @@
{2} {3}
Congratulations!
We have created your new account on {0},
associated with {4}.
If you did not request this new account you can safely ignore this email.
This request will expire if not acted upon for 30 days.
Paste the link below into your browser's address bar to create your password
for your new account using our secure server.
{5}
Thanks!

View file

@ -0,0 +1,22 @@
<html>
<head>
<title>${1}</title>
</head>
<body>
<p>
${2} ${3}
</p>
<p>
<strong>Congratulations!</strong>
</p>
<p>
We have created your new VIVO account associated with ${4}.
</p>
<p>
Thanks!
</p>
</body>
</html>

View file

@ -0,0 +1,9 @@
${2} ${3}
Congratulations!
We have created your new VIVO account associated with
${4}.
Thanks!

View file

@ -0,0 +1,19 @@
<html>
<head>
<title>{1}</title>
</head>
<body>
<p>
Hi, {2} ${3}
</p>
<p>
You recently changed the email address associated with
${2} ${3}
</p>
<p>
Thank you.
</p>
</body>
</html>

View file

@ -0,0 +1,6 @@
Hi, {2} {3}
You recently changed the email address associated with
{2} {3}
Thank you.

View file

@ -0,0 +1,22 @@
<html>
<head>
<title>{1}</title>
</head>
<body>
<p>
{2} {3}
</p>
<p>
<strong>Congratulations!</strong>
</p>
<p>
We have created your new {0} account associated with {4}.
</p>
<p>
Thanks!
</p>
</body>
</html>

View file

@ -0,0 +1,8 @@
{2} {3}
Congratulations!
We have created your new {0} account associated with
{4}
Thanks!

View file

@ -0,0 +1,22 @@
<html>
<head>
<title>{1}</title>
</head>
<body>
<p>
{2} {3}
</p>
<p>
<strong>Password successfully created.</strong>
</p>
<p>
Your new password associated with {4} has been created.
</p>
<p>
Thank you.
</p>
</body>
</html>

View file

@ -0,0 +1,8 @@
{2} {3}
Password successfully created.
Your new password associated with {4}
has been created.
Thank you.

View file

@ -0,0 +1,34 @@
<html>
<head>
<title>{1}</title>
</head>
<body>
<p>
Dear {2} {3}:
</p>
<p>
We have received a request to reset the password for your {0} account ({4}).
</p>
<p>
Please follow the instructions below to proceed with your password reset.
</p>
<p>
If you did not request this new account you can safely ignore this email.
This request will expire if not acted upon within 30 days.
</p>
<p>
Click on the link below or paste it into your browser's address bar to reset your password
using our secure server.
</p>
<p>
<a href="{5}" title="password">{5}</a>
</p>
<p>Thank you!</p>
</body>
</html>

View file

@ -0,0 +1,16 @@
Dear {2} {3}:
We have received a request to reset the password for your {0} account
({4}).
Please follow the instructions below to proceed with your password reset.
If you did not request this new account you can safely ignore this email.
This request will expire if not acted upon within 30 days.
Paste the link below into your browser's address bar to reset your password
using our secure server.
{5}
Thank you!

View file

@ -0,0 +1,22 @@
<html>
<head>
<title>{1}</title>
</head>
<body>
<p>
{2} {3}
</p>
<p>
<strong>Password successfully changed.</strong>
</p>
<p>
Your new password associated with {4} has been changed.
</p>
<p>
Thank you.
</p>
</body>
</html>

View file

@ -0,0 +1,8 @@
{2} {3}
Password successfully changed.
Your new password associated with {4}
has been changed.
Thank you.

View file

@ -0,0 +1,34 @@
<html>
<head>
<title>{1}</title>
</head>
<body>
<p>
Dear {2} {3}:
</p>
<p>
We have received a request to reset the password for your {0} account ({4}).
</p>
<p>
Please follow the instructions below to proceed with your password reset.
</p>
<p>
If you did not request this new account you can safely ignore this email.
This request will expire if not acted upon within 30 days.
</p>
<p>
Click on the link below or paste it into your browser's address bar to reset your password
using our secure server.
</p>
<p>
<a href="{5}" title="password">{5}</a>
</p>
<p>Thank you!</p>
</body>
</html>

View file

@ -0,0 +1,16 @@
Dear {2} {3}:
We have received a request to reset the password for your {0} account
({4}).
Please follow the instructions below to proceed with your password reset.
If you did not request this new account you can safely ignore this email.
This request will expire if not acted upon within 30 days.
Paste the link below into your browser's address bar to reset your password
using our secure server.
{5}
Thank you!

View file

@ -45,7 +45,7 @@ $(document).ready(function(){
if (countAccount == 0){ if (countAccount == 0){
return false; return false;
}else{ }else{
var answer = confirm( 'Are you sure you want to delete ' + ((countAccount > 1) ? 'these accounts' : 'this account') +'?'); var answer = confirm( ((countAccount > 1) ? confirm_delete_account_plural : confirm_delete_account_singular) +'?');
return answer; return answer;
} }
}); });

View file

@ -4,7 +4,7 @@ $(document).ready(function(){
// Confirmation alert for photo deletion in image upload and individual templates // Confirmation alert for photo deletion in image upload and individual templates
$('#photoUploadDefaultImage a.thumbnail, a.delete-mainImage').click(function(){ $('#photoUploadDefaultImage a.thumbnail, a.delete-mainImage').click(function(){
var answer = confirm('Are you sure you want to delete this photo?'); var answer = confirm(i18n_confirmDelete);
return answer; return answer;
}); });
}); });

View file

@ -2,67 +2,22 @@
<#-- Confirmation that an account has been created. --> <#-- Confirmation that an account has been created. -->
<#assign subject = "Your ${siteName} account has been created." /> <#assign strings = i18n() />
<#assign html> <#assign subject = strings.account_created(siteName) />
<html>
<head>
<title>${subject}</title>
</head>
<body>
<p>
${userAccount.firstName} ${userAccount.lastName}
</p>
<p> <#assign html = strings.account_created_email_html(siteName,
<strong>Congratulations!</strong> subject,
</p> userAccount.firstName,
userAccount.lastName,
userAccount.emailAddress,
passwordLink) />
<p> <#assign text = strings.account_created_email_text(siteName,
We have created your new account on ${siteName}, associated with ${userAccount.emailAddress}. subject,
</p> userAccount.firstName,
userAccount.lastName,
<p> userAccount.emailAddress,
If you did not request this new account you can safely ignore this email. passwordLink) />
This request will expire if not acted upon for 30 days.
</p>
<p>
Click the link below to create your password for your new account using our secure server.
</p>
<p>
<a href="${passwordLink}" title="password">${passwordLink}</a>
</p>
<p>
If the link above doesn't work, you can copy and paste the link directly into your browser's address bar.
</p>
<p>
Thanks!
</p>
</body>
</html>
</#assign>
<#assign text>
${userAccount.firstName} ${userAccount.lastName}
Congratulations!
We have created your new account on ${siteName},
associated with ${userAccount.emailAddress}.
If you did not request this new account you can safely ignore this email.
This request will expire if not acted upon for 30 days.
Paste the link below into your browser's address bar to create your password
for your new account using our secure server.
${passwordLink}
Thanks!
</#assign>
<@email subject=subject html=html text=text /> <@email subject=subject html=html text=text />

View file

@ -2,42 +2,18 @@
<#-- Confirmation that an account has been created. --> <#-- Confirmation that an account has been created. -->
<#assign subject = "Your ${siteName} account has been created." /> <#assign subject = strings.account_created(siteName) />
<#assign html> <#assign html = strings.account_created_external_email_html(siteName,
<html> subject,
<head> userAccount.firstName,
<title>${subject}</title> userAccount.lastName,
</head> userAccount.emailAddress) />
<body>
<p>
${userAccount.firstName} ${userAccount.lastName}
</p>
<p> <#assign text = string.account_created_external_email_text(siteName,
<strong>Congratulations!</strong> subject,
</p> userAccount.firstName,
userAccount.lastName,
<p> userAccount.emailAddress) />
We have created your new VIVO account associated with ${userAccount.emailAddress}.
</p>
<p>
Thanks!
</p>
</body>
</html>
</#assign>
<#assign text>
${userAccount.firstName} ${userAccount.lastName}
Congratulations!
We have created your new VIVO account associated with
${userAccount.emailAddress}.
Thanks!
</#assign>
<@email subject=subject html=html text=text /> <@email subject=subject html=html text=text />

View file

@ -2,71 +2,54 @@
<#-- Template for adding a user account --> <#-- Template for adding a user account -->
<h3><a class="account-menu" href="accountsAdmin" title="add new account">User accounts</a> > Add new account</h3> <#assign strings = i18n() />
<h3><a class="account-menu" href="accountsAdmin" title="${strings.user_accounts_title}">${strings.user_accounts_link}</a> > ${strings.add_new_account}</h3>
<#if errorEmailIsEmpty??> <#if errorEmailIsEmpty??>
<#assign errorMessage = "You must supply an email address." /> <#assign errorMessage = strings.error_no_email />
</#if> <#elseif errorEmailInUse??>
<#assign errorMessage = strings.error_email_already_exists />
<#if errorEmailInUse??> <#elseif errorEmailInvalidFormat??>
<#assign errorMessage = "An account with that email address already exists." /> <#assign errorMessage = strings.error_invalid_email(emailAddress) />
</#if> <#elseif errorExternalAuthIdInUse??>
<#assign errorMessage = strings.error_external_auth_already_exists />
<#if errorEmailInvalidFormat??> <#elseif errorFirstNameIsEmpty??>
<#assign errorMessage = "'${emailAddress}' is not a valid email address." /> <#assign errorMessage = strings.error_no_first_name />
</#if> <#elseif errorLastNameIsEmpty??>
<#assign errorMessage = strings.error_no_last_name />
<#if errorExternalAuthIdInUse??> <#elseif errorNoRoleSelected??>
<#assign errorMessage = "An account with that external authorization ID already exists." /> <#assign errorMessage = strings.error_no_role />
</#if> <#elseif errorPasswordIsEmpty??>
<#assign errorMessage = strings.error_no_password />
<#if errorFirstNameIsEmpty??> <#elseif errorPasswordIsWrongLength??>
<#assign errorMessage = "You must supply a first name." /> <#assign errorMessage = strings.error_password_length(minimumLength, maximumLength) />
</#if> <#elseif errorPasswordsDontMatch??>
<#assign errorMessage = strings.error_password_mismatch />
<#if errorLastNameIsEmpty??>
<#assign errorMessage = "You must supply a last name." />
</#if>
<#if errorNoRoleSelected??>
<#assign errorMessage = "You must select a role." />
</#if>
<#if errorPasswordIsEmpty??>
<#assign errorMessage = "No password supplied." />
</#if>
<#if errorPasswordIsWrongLength??>
<#assign errorMessage = "Password must be between ${minimumLength} and ${maximumLength} characters." />
</#if>
<#if errorPasswordsDontMatch??>
<#assign errorMessage = "Passwords do not match." />
</#if> </#if>
<#if errorMessage?has_content> <#if errorMessage?has_content>
<section id="error-alert" role="alert"> <section id="error-alert" role="alert">
<img src="${urls.images}/iconAlert.png" width="24" height="24" alert="Error alert icon" /> <img src="${urls.images}/iconAlert.png" width="24" height="24" alert="${strings.alt_error_alert}" />
<p>${errorMessage}</p> <p>${errorMessage}</p>
</section> </section>
</#if> </#if>
<section id="add-account" role="region"> <section id="add-account" role="region">
<form method="POST" action="${formUrls.add}" class="customForm" role="add new account"> <form method="POST" action="${formUrls.add}" class="customForm" role="add new account">
<label for="email-address">Email address<span class="requiredHint"> *</span></label> <label for="email-address">${strings.email_address}<span class="requiredHint"> *</span></label>
<input type="text" name="emailAddress" value="${emailAddress}" id="email-address" role="input" /> <input type="text" name="emailAddress" value="${emailAddress}" id="email-address" role="input" />
<label for="first-name">First name<span class="requiredHint"> *</span></label> <label for="first-name">${strings.first_name}<span class="requiredHint"> *</span></label>
<input type="text" name="firstName" value="${firstName}" id="first-name" role="input" /> <input type="text" name="firstName" value="${firstName}" id="first-name" role="input" />
<label for="last-name">Last name<span class="requiredHint"> *</span></label> <label for="last-name">${strings.last_name}<span class="requiredHint"> *</span></label>
<input type="text" name="lastName" value="${lastName}" id="last-name" role="input" /> <input type="text" name="lastName" value="${lastName}" id="last-name" role="input" />
<#include "userAccounts-associateProfilePanel.ftl"> <#include "userAccounts-associateProfilePanel.ftl">
<p><input id="externalAuthChkBox" type="checkbox" name="externalAuthOnly" <#if externalAuthOnly?? >checked</#if> />Externally Authenticated Only</p> <p><input id="externalAuthChkBox" type="checkbox" name="externalAuthOnly" <#if externalAuthOnly?? >checked</#if> />${strings.external_auth_only}</p>
<p>Roles<span class="requiredHint"> *</span></p> <p>${strings.roles}<span class="requiredHint"> *</span></p>
<#list roles as role> <#list roles as role>
<input type="radio" name="role" value="${role.uri}" role="radio" ${selectedRoles?seq_contains(role.uri)?string("checked", "")} /> <input type="radio" name="role" value="${role.uri}" role="radio" ${selectedRoles?seq_contains(role.uri)?string("checked", "")} />
<label class="inline" for="${role.label}"> ${role.label}</label> <label class="inline" for="${role.label}"> ${role.label}</label>
@ -74,25 +57,21 @@
</#list> </#list>
<#if emailIsEnabled??> <#if emailIsEnabled??>
<p class="note"> <p class="note">${strings.new_account_note}</p>
Note: An email will be sent to the address entered above
notifying that an account has been created.
It will include instructions for activating the account and creating a password.
</p>
<#else> <#else>
<section id="passwordContainer" role="region"> <section id="passwordContainer" role="region">
<label for="initial-password">Initial password<span class="requiredHint"> *</span></label> <label for="initial-password">${strings.initial_password}<span class="requiredHint"> *</span></label>
<input type="password" name="initialPassword" value="${initialPassword}" id="initial-password" role="input" /> <input type="password" name="initialPassword" value="${initialPassword}" id="initial-password" role="input" />
<p class="note">Minimum of ${minimumLength} characters in length.</p> <p class="note">${strings.minimum_password_length}</p>
<label for="confirm-password">Confirm initial password<span class="requiredHint"> *</span></label> <label for="confirm-password">${strings.confirm_initial_password}<span class="requiredHint"> *</span></label>
<input type="password" name="confirmPassword" value="${confirmPassword}" id="confirm-password" role="input" /> <input type="password" name="confirmPassword" value="${confirmPassword}" id="confirm-password" role="input" />
</section> </section>
</#if> </#if>
<p><input type="submit" name="submitAdd" value="Add new account" class="submit" /> or <a class="cancel" href="${formUrls.list}" title="cancel">Cancel</a></p> <p><input type="submit" name="submitAdd" value="${strings.submit_add_new_account}" class="submit" /> ${strings.or} <a class="cancel" href="${formUrls.list}" title="${strings.cancel_title}">${strings.cancel_link}</a></p>
<p class="requiredHint">* required fields</p> <p class="requiredHint">* ${strings.required_fields}</p>
</form> </form>
</section> </section>

View file

@ -2,20 +2,22 @@
<#-- Template for setting the account reference field, which can also associate a profile with the user account --> <#-- Template for setting the account reference field, which can also associate a profile with the user account -->
<#assign strings = i18n() />
${stylesheets.add('<link rel="stylesheet" href="${urls.base}/edit/forms/css/autocomplete.css" />', ${stylesheets.add('<link rel="stylesheet" href="${urls.base}/edit/forms/css/autocomplete.css" />',
'<link rel="stylesheet" href="${urls.base}/js/jquery-ui/css/smoothness/jquery-ui-1.8.9.custom.css" />')} '<link rel="stylesheet" href="${urls.base}/js/jquery-ui/css/smoothness/jquery-ui-1.8.9.custom.css" />')}
<section id="externalAuthMatchId"> <section id="externalAuthMatchId">
<div id="associateProfileBackgroundOne"> <div id="associateProfileBackgroundOne">
<div id="alignExternalAuthId"> <div id="alignExternalAuthId">
<#if showAssociation??> <#if showAssociation??>
<label for="externalAuthId">External Auth. ID / Matching ID</label> <label for="externalAuthId">${strings.auth_matching_id_label}</label>
<input type="text" name="externalAuthId" value="${externalAuthId}" id="externalAuthId" role="input "/> <input type="text" name="externalAuthId" value="${externalAuthId}" id="externalAuthId" role="input "/>
<span id="externalAuthIdInUse" >This Identifier is already in use.</span> <span id="externalAuthIdInUse" >${strings.auth_id_in_use}</span>
<p class="explanatoryText">Can be used to associate the account with the user's profile via the matching property.</p> <p class="explanatoryText">${strings.auth_id_explanation}</p>
<#else> <#else>
<label for="externalAuthId">External Authentication ID</label> <label for="externalAuthId">${strings.auth_id_label}</label>
<input type="text" name="externalAuthId" value="${externalAuthId}" id="externalAuthId" role="input "/> <input type="text" name="externalAuthId" value="${externalAuthId}" id="externalAuthId" role="input "/>
<span id="externalAuthIdInUse" >This Identifier is already in use.</span> <span id="externalAuthIdInUse" >${strings.auth_id_in_use}</span>
</#if> </#if>
</div> </div>
</div> </div>
@ -24,10 +26,10 @@ ${stylesheets.add('<link rel="stylesheet" href="${urls.base}/edit/forms/css/auto
<section id="associated"> <section id="associated">
<div id="associateProfileBackgroundTwo"> <div id="associateProfileBackgroundTwo">
<p> <p>
<label for="associatedProfileName">Associated profile:</label> <label for="associatedProfileName">${strings.associated_profile_label}</label>
<span class="acSelectionInfo" id="associatedProfileName"></span> <span class="acSelectionInfo" id="associatedProfileName"></span>
<a href="" id="verifyProfileLink" title="verify this match">(verify this match)</a> <a href="" id="verifyProfileLink" title="${strings.verify_this_match_title}">(${strings.verify_this_match})</a>
<a href="" id="changeProfileLink" title="change profile">(change profile)</a> <a href="" id="changeProfileLink" title="${strings.change_profile_title}">(${strings.change_profile})</a>
</p> </p>
<input type="hidden" id="associatedProfileUri" name="associatedProfileUri" value="" /> <input type="hidden" id="associatedProfileUri" name="associatedProfileUri" value="" />
</div> </div>
@ -37,16 +39,16 @@ ${stylesheets.add('<link rel="stylesheet" href="${urls.base}/edit/forms/css/auto
<section id="associationOptions"> <section id="associationOptions">
<div id="associateProfileBackgroundThree"> <div id="associateProfileBackgroundThree">
<p> <p>
<label for="associateProfileName">Select the associated profile</label> <label for="associateProfileName">${strings.select_associated_profile}</label>
<input type="text" id="associateProfileName" name="associateProfileName" class="acSelector" size="35"> <input type="text" id="associateProfileName" name="associateProfileName" class="acSelector" size="35">
</p> </p>
</div> </div>
<div id="associateProfileBackgroundFour"> <div id="associateProfileBackgroundFour">
<p> - or - </p> <p> - ${strings.or} - </p>
<p> <p>
<label for="">Create the associated profile</label> <label for="">${strings.create_associated_profile}</label>
<select name="newProfileClassUri" id="newProfileClassUri" > <select name="newProfileClassUri" id="newProfileClassUri" >
<option value="" selected="selected">Select one</option> <option value="" selected="selected">${strings.select_one}</option>
<#list profileTypes?keys as key> <#list profileTypes?keys as key>
<option value="${key}" <#if newProfileClassUri = key> selected </#if> >${profileTypes[key]}</option> <option value="${key}" <#if newProfileClassUri = key> selected </#if> >${profileTypes[key]}</option>
</#list> </#list>

View file

@ -2,37 +2,20 @@
<#-- Confirmation that the user has changed his email account. --> <#-- Confirmation that the user has changed his email account. -->
<#assign subject = "Your ${siteName} email account has been changed." /> <#assign strings = i18n() />
<#assign html> <#assign subject = strings.email_changed_subject(siteName) />
<html>
<head>
<title>${subject}</title>
</head>
<body>
<p>
Hi, ${userAccount.firstName} ${userAccount.lastName}
</p>
<p> <#assign html = strings.email_changed_html(siteName,
You recently changed the email address associated with subject,
${userAccount.firstName} ${userAccount.lastName} userAccount.firstName,
</p> userAccount.lastName,
userAccount.emailAddress) />
<p> <#assign text = strings.email_changed_text(siteName,
Thank you. subject,
</p> userAccount.firstName,
</body> userAccount.lastName,
</html> userAccount.emailAddress) />
</#assign>
<#assign text>
Hi, ${userAccount.firstName} ${userAccount.lastName}
You recently changed the email address associated with
${userAccount.firstName} ${userAccount.lastName}
Thank you.
</#assign>
<@email subject=subject html=html text=text /> <@email subject=subject html=html text=text />

View file

@ -2,44 +2,43 @@
<#-- Template for adding a user account --> <#-- Template for adding a user account -->
<h3>Create your Password</h3> <#assign strings = i18n() />
<h3>${strings.create_your_password}</h3>
<#if errorPasswordIsEmpty??> <#if errorPasswordIsEmpty??>
<#assign errorMessage = "No password supplied." /> <#assign errorMessage = strings.error_no_password />
</#if> <#elseif errorPasswordIsWrongLength??>
<#assign errorMessage = strings.error_password_length(minimumLength, maximumLength) />
<#if errorPasswordIsWrongLength??> <#elseif errorPasswordsDontMatch??>
<#assign errorMessage = "Password must be between ${minimumLength} and ${maximumLength} characters." /> <#assign errorMessage = strings.error_password_mismatch />
</#if>
<#if errorPasswordsDontMatch??>
<#assign errorMessage = "Passwords do not match." />
</#if> </#if>
<#if errorMessage?has_content> <#if errorMessage?has_content>
<section id="error-alert" role="alert"> <section id="error-alert" role="alert">
<img src="${urls.images}/iconAlert.png" width="24" height="24" alert="Error alert icon"/> <img src="${urls.images}/iconAlert.png" width="24" height="24" alert="${strings.alt_error_alert}"/>
<p>${errorMessage}</p> <p>${errorMessage}</p>
</section> </section>
</#if> </#if>
<section id="create-password" role="region"> <section id="create-password" role="region">
<p>Please enter your new password for ${userAccount.emailAddress}</p> <p>${strings.enter_new_password(userAccount.emailAddress)}</p>
<form method="POST" action="${formUrls.createPassword}" class="customForm" role="create password"> <form method="POST" action="${formUrls.createPassword}" class="customForm" role="create password">
<input type="hidden" name="user" value="${userAccount.emailAddress}" role="input" /> <input type="hidden" name="user" value="${userAccount.emailAddress}" role="input" />
<input type="hidden" name="key" value="${userAccount.passwordLinkExpiresHash}" role="input" /> <input type="hidden" name="key" value="${userAccount.passwordLinkExpiresHash}" role="input" />
<label for="new-password">Password<span class="requiredHint"> *</span></label> <label for="new-password">${strings.new_password}<span class="requiredHint"> *</span></label>
<input type="password" name="newPassword" value="${newPassword}" id="new-password" role="input" /> <input type="password" name="newPassword" value="${newPassword}" id="new-password" role="input" />
<p class="note">Minimum of ${minimumLength} characters in length.</p> <p class="note">${strings.minimum_password_length(minimumLength)}</p>
<label for="confirm-password">Confirm Password<span class="requiredHint"> *</span></label> <label for="confirm-password">${strings.confirm_password}<span class="requiredHint"> *</span></label>
<input type="password" name="confirmPassword" value="${confirmPassword}" id="confirm-password" role="input" /> <input type="password" name="confirmPassword" value="${confirmPassword}" id="confirm-password" role="input" />
<p><input type="submit" name="submit" value="Save changes" class="submit"/></p> <p><input type="submit" name="submit" value="${strings.save_changes}" class="submit"/></p>
<p class="requiredHint">* required fields</p> <p class="requiredHint">* ${strings.required_fields}</p>
</form> </form>
</section> </section>

View file

@ -2,75 +2,58 @@
<#-- Template for editing a user account --> <#-- Template for editing a user account -->
<h3><a class="account-menu" href="accountsAdmin" title="edit account">User accounts</a> > Edit account</h3> <#assign strings = i18n() />
<h3><a class="account-menu" href="accountsAdmin" title="${strings.user_accounts_title}">${strings.user_accounts_link}</a> > ${strings.edit_account}</h3>
<#if errorEmailIsEmpty??> <#if errorEmailIsEmpty??>
<#assign errorMessage = "You must supply an email address." /> <#assign errorMessage = strings.error_no_email />
</#if> <#elseif errorEmailInUse??>
<#assign errorMessage = strings.error_email_already_exists />
<#if errorEmailInUse??> <#elseif errorEmailInvalidFormat??>
<#assign errorMessage = "An account with that email address already exists." /> <#assign errorMessage = strings.error_invalid_email(emailAddress) />
</#if> <#elseif errorExternalAuthIdInUse??>
<#assign errorMessage = strings.error_external_auth_already_exists />
<#if errorEmailInvalidFormat??> <#elseif errorFirstNameIsEmpty??>
<#assign errorMessage = "'${emailAddress}' is not a valid email address." /> <#assign errorMessage = strings.error_no_first_name />
</#if> <#elseif errorLastNameIsEmpty??>
<#assign errorMessage = strings.error_no_last_name />
<#if errorExternalAuthIdInUse??> <#elseif errorNoRoleSelected??>
<#assign errorMessage = "An account with that external authorization ID already exists." /> <#assign errorMessage = strings.error_no_role />
</#if> <#elseif errorPasswordIsEmpty??>
<#assign errorMessage = strings.error_no_password />
<#if errorFirstNameIsEmpty??> <#elseif errorPasswordIsWrongLength??>
<#assign errorMessage = "You must supply a first name." /> <#assign errorMessage = strings.error_password_length(minimumLength, maximumLength) />
</#if> <#elseif errorPasswordsDontMatch??>
<#assign errorMessage = strings.error_password_mismatch />
<#if errorLastNameIsEmpty??>
<#assign errorMessage = "You must supply a last name." />
</#if>
<#if errorNoRoleSelected??>
<#assign errorMessage = "You must select a role." />
</#if>
<#if errorPasswordIsEmpty??>
<#assign errorMessage = "No password supplied." />
</#if>
<#if errorPasswordIsWrongLength??>
<#assign errorMessage = "Password must be between ${minimumLength} and ${maximumLength} characters." />
</#if>
<#if errorPasswordsDontMatch??>
<#assign errorMessage = "Passwords do not match." />
</#if> </#if>
<#if errorMessage?has_content> <#if errorMessage?has_content>
<section id="error-alert" role="alert"> <section id="error-alert" role="alert">
<img src="${urls.images}/iconAlert.png" width="24" height="24" alert="Error alert icon" /> <img src="${urls.images}/iconAlert.png" width="24" height="24" alert="${strings.alt_error_alert}" />
<p>${errorMessage}</p> <p>${errorMessage}</p>
</section> </section>
</#if> </#if>
<section id="edit-account" role="region"> <section id="edit-account" role="region">
<form method="POST" action="${formUrls.edit}" id="userAccountForm" class="customForm" role="edit account"> <form method="POST" action="${formUrls.edit}" id="userAccountForm" class="customForm" role="edit account">
<label for="email-address">Email address<span class="requiredHint"> *</span></label> <label for="email-address">${strings.email_address}<span class="requiredHint"> *</span></label>
<input type="text" name="emailAddress" value="${emailAddress}" id="email-address" role="input" /> <input type="text" name="emailAddress" value="${emailAddress}" id="email-address" role="input" />
<label for="first-name">First name<span class="requiredHint"> *</span></label> <label for="first-name">${strings.first_name}<span class="requiredHint"> *</span></label>
<input type="text" name="firstName" value="${firstName}" id="first-name" role="input" /> <input type="text" name="firstName" value="${firstName}" id="first-name" role="input" />
<label for="last-name">Last name<span class="requiredHint"> *</span></label> <label for="last-name">${strings.last_name}<span class="requiredHint"> *</span></label>
<input type="text" name="lastName" value="${lastName}" id="last-name" role="input" /> <input type="text" name="lastName" value="${lastName}" id="last-name" role="input" />
<#if externalAuthPermitted??> <#if externalAuthPermitted??>
<#include "userAccounts-associateProfilePanel.ftl"> <#include "userAccounts-associateProfilePanel.ftl">
<p><input id="externalAuthChkBox" type="checkbox" name="externalAuthOnly" <#if externalAuthOnly?? >checked</#if> />Externally Authenticated Only</p> <p><input id="externalAuthChkBox" type="checkbox" name="externalAuthOnly" <#if externalAuthOnly?? >checked</#if> />${strings.external_auth_only}</p>
</#if> </#if>
<#if roles?has_content> <#if roles?has_content>
<p>Roles<span class="requiredHint"> *</span></p> <p>${strings.roles}<span class="requiredHint"> *</span></p>
<#list roles as role> <#list roles as role>
<input type="radio" name="role" value="${role.uri}" role="radio" ${selectedRoles?seq_contains(role.uri)?string("checked", "")} /> <input type="radio" name="role" value="${role.uri}" role="radio" ${selectedRoles?seq_contains(role.uri)?string("checked", "")} />
<label class="inline" for="${role.label}"> ${role.label}</label> <label class="inline" for="${role.label}"> ${role.label}</label>
@ -81,29 +64,25 @@
<#if emailIsEnabled??> <#if emailIsEnabled??>
<section id="pwdResetContainer" <#if externalAuthOnly?? >class="hidden"</#if> role="region"> <section id="pwdResetContainer" <#if externalAuthOnly?? >class="hidden"</#if> role="region">
<input type="checkbox" name="resetPassword" value="" id="reset-password" role="checkbox" <#if resetPassword??>checked</#if> /> <input type="checkbox" name="resetPassword" value="" id="reset-password" role="checkbox" <#if resetPassword??>checked</#if> />
<label class="inline" for="reset-password"> Reset password</label> <label class="inline" for="reset-password">${strings.reset_password}</label>
<p class="note"> <p class="note">${strings.reset_password_note}</p>
Note: Instructions for resetting the password will
be emailed to the address entered above. The password will not
be reset until the user follows the link provided in this email.
</p>
</section> </section>
<#else> <#else>
<section id="passwordContainer" <#if externalAuthOnly?? >class="hidden"</#if> role="region"> <section id="passwordContainer" <#if externalAuthOnly?? >class="hidden"</#if> role="region">
<label for="new-password">New password</label> <label for="new-password">${strings.new_password}</label>
<input type="password" name="newPassword" value="${newPassword}" id="new-password" role="input" /> <input type="password" name="newPassword" value="${newPassword}" id="new-password" role="input" />
<p class="note">Minimum of ${minimumLength} characters in length.<br /> <p class="note">${strings.minimum_password_length(minimumLength)}<br />
Leaving this blank means that the password will not be changed.</p> ${strings.leave_password_unchanged}</p>
<label for="confirm-password">Confirm new password</label> <label for="confirm-password">${strings.confirm_password}</label>
<input type="password" name="confirmPassword" value="${confirmPassword}" id="confirm-password" role="input" /> <input type="password" name="confirmPassword" value="${confirmPassword}" id="confirm-password" role="input" />
</section> </section>
</#if> </#if>
<p><input type="submit" id="submitMyAccount" name="submitEdit" value="Save changes" class="submit" disabled /> or <a class="cancel" href="${formUrls.list}" title="cancel">Cancel</a></p> <p><input type="submit" id="submitMyAccount" name="submitEdit" value="${strings.save_changes}" class="submit" disabled /> ${strings.or} <a class="cancel" href="${formUrls.list}" title="${strings.cancel_title}">${strings.cancel_link}</a></p>
<p class="requiredHint">* required fields</p> <p class="requiredHint">* ${strings.required_fields}</p>
</form> </form>
</section> </section>

View file

@ -2,59 +2,55 @@
<#-- Template for creating an account for the first time an external user logs in. --> <#-- Template for creating an account for the first time an external user logs in. -->
<h3>First time log in</h3> <#assign strings = i18n() />
<h3>${strings.first_time_login}</h3>
<#if errorEmailIsEmpty??> <#if errorEmailIsEmpty??>
<#assign errorMessage = "You must supply an email address." /> <#assign errorMessage = strings.error_no_email />
</#if> <#elseif errorEmailInUse??>
<#assign errorMessage = strings.error_email_already_exists />
<#if errorEmailInUse??> <#elseif errorEmailInvalidFormat??>
<#assign errorMessage = "An account with that email address already exists." /> <#assign errorMessage = strings.error_invalid_email(emailAddress) />
</#if> <#elseif errorFirstNameIsEmpty??>
<#assign errorMessage = strings.error_no_first_name />
<#if errorEmailInvalidFormat??> <#elseif errorLastNameIsEmpty??>
<#assign errorMessage = "'${emailAddress}' is not a valid email address." /> <#assign errorMessage = strings.error_no_last_name />
</#if>
<#if errorFirstNameIsEmpty??>
<#assign errorMessage = "You must supply a first name." />
</#if>
<#if errorLastNameIsEmpty??>
<#assign errorMessage = "You must supply a last name." />
</#if> </#if>
<#if errorMessage?has_content> <#if errorMessage?has_content>
<section id="error-alert" role="alert"> <section id="error-alert" role="alert">
<img src="${urls.images}/iconAlert.png" width="24" height="24" alert="Error alert icon"/> <img src="${urls.images}/iconAlert.png" width="24" height="24" alert="${strings.alt_error_alert}" />
<p>${errorMessage}</p> <p>${errorMessage}</p>
</section> </section>
</#if> </#if>
<section id="first-time-login" role="region"> <section id="first-time-login" role="region">
<p>Please provide your contact information to finish creating your account.</p> <p>${strings.please_provide_contact_information}</p>
<form method="POST" action="${formUrls.firstTimeExternal}" class="customForm" role="my account"> <form method="POST" action="${formUrls.firstTimeExternal}" class="customForm" role="my account">
<input type="hidden" name="externalAuthId" value="${externalAuthId}" role="input" /> <input type="hidden" name="externalAuthId" value="${externalAuthId}" role="input" />
<input type="hidden" name="afterLoginUrl" value="${afterLoginUrl}" role="input" /> <input type="hidden" name="afterLoginUrl" value="${afterLoginUrl}" role="input" />
<label for="first-name">First name<span class="requiredHint"> *</span></label> <label for="first-name">${strings.first_name}<span class="requiredHint"> *</span></label>
<input type="text" name="firstName" value="${firstName}" id="first-name" role="input" /> <input type="text" name="firstName" value="${firstName}" id="first-name" role="input" />
<label for="last-name">Last name<span class="requiredHint"> *</span></label> <label for="last-name">${strings.last_name}<span class="requiredHint"> *</span></label>
<input type="text" name="lastName" value="${lastName}" id="last-name" role="input" /> <input type="text" name="lastName" value="${lastName}" id="last-name" role="input" />
<label for="email-address">Email address<span class="requiredHint"> *</span></label> <label for="email-address">${strings.email_address}<span class="requiredHint"> *</span></label>
<input type="text" name="emailAddress" value="${emailAddress}" id="email-address" role="input" /> <input type="text" name="emailAddress" value="${emailAddress}" id="email-address" role="input" />
<#if emailIsEnabled??> <#if emailIsEnabled??>
<p class="note"> <p class="note">${strings.first_time_login_note}</p>
Note: An email will be sent to the address entered above notifying
that an account has been created.
</p>
</#if> </#if>
<p><input type="submit" name="submit" value="Create account" class="submit"/> or <a class="cancel" href="${urls.home}" title="cancel">Cancel</a></p> <p><input type="submit" name="submit" value="${strings.create_account}" class="submit"/>
${strings.or}
<a class="cancel" href="${urls.home}" title="${string.cancel_title}">${strings.cancel_link}</a>
</p>
<p class="requiredHint">* ${strings.required_fields}</p>
</form> </form>
</section> </section>

View file

@ -2,42 +2,20 @@
<#-- Confirmation that an account has been created for an externally-authenticated user. --> <#-- Confirmation that an account has been created for an externally-authenticated user. -->
<#assign subject = "Your ${siteName} account has been created." /> <#assign strings = i18n() />
<#assign html> <#assign subject = strings.account_created(siteName) />
<html>
<head>
<title>${subject}</title>
</head>
<body>
<p>
${userAccount.firstName} ${userAccount.lastName}
</p>
<p> <#assign html = strings.first_time_external_email_html(siteName,
<strong>Congratulations!</strong> subject,
</p> userAccount.firstName,
userAccount.lastName,
userAccount.emailAddress) />
<p> <#assign text = strings.first_time_external_email_text(siteName,
We have created your new VIVO account associated with ${userAccount.emailAddress}. subject,
</p> userAccount.firstName,
userAccount.lastName,
<p> userAccount.emailAddress) />
Thanks!
</p>
</body>
</html>
</#assign>
<#assign text>
${userAccount.firstName} ${userAccount.lastName}
Congratulations!
We have created your new VIVO account associated with
${userAccount.emailAddress}.
Thanks!
</#assign>
<@email subject=subject html=html text=text /> <@email subject=subject html=html text=text />

View file

@ -4,20 +4,19 @@
<#import "userAccounts-accountsNav.ftl" as p> <#import "userAccounts-accountsNav.ftl" as p>
<#assign strings = i18n() />
<form method="POST" action="${formUrls.add}" id="add-account" class="customForm" role="Add account"> <form method="POST" action="${formUrls.add}" id="add-account" class="customForm" role="Add account">
<h3><span>User accounts | </span><input type="submit" class="submit add-account" value="Add new account" /></h3> <h3><span>${strings.user_accounts_link} | </span><input type="submit" class="submit add-account" value="${strings.add_new_account}" /></h3>
</form> </form>
<#if newUserAccount?? > <#if newUserAccount?? >
<section class="account-feedback"> <section class="account-feedback">
<p> <p>
A new account for ${strings.new_account_1}
<a href="${newUserAccount.editUrl}" title="new account">${newUserAccount.firstName} ${newUserAccount.lastName}</a> <a href="${newUserAccount.editUrl}" title="${strings.new_account_title}">${newUserAccount.firstName} ${newUserAccount.lastName}</a>
was successfully created. ${strings.new_account_2}
<#if emailWasSent?? > <#if emailWasSent?? >${strings.new_account_notification(newUserAccount.emailAddress)}</#if>
A notification email has been sent to ${newUserAccount.emailAddress}
with instructions for activating the account and creating a password.
</#if>
</p> </p>
</section> </section>
</#if> </#if>
@ -25,14 +24,10 @@
<#if updatedUserAccount?? > <#if updatedUserAccount?? >
<section class="account-feedback"> <section class="account-feedback">
<p> <p>
The account for ${strings.updated_account_1}
<a href="${updatedUserAccount.editUrl}" title="updated account">${updatedUserAccount.firstName} ${updatedUserAccount.lastName}</a> <a href="${updatedUserAccount.editUrl}" title="${strings.updated_account_title}}">${updatedUserAccount.firstName} ${updatedUserAccount.lastName}</a>
has been updated. ${strings.updated_account_2}
<#if emailWasSent?? > <#if emailWasSent?? >${strings.updated_account_notification(updatedUserAccount.emailAddress)}</#if>
A confirmation email has been sent to ${updatedUserAccount.emailAddress}
with instructions for resetting a password.
The password will not be reset until the user follows the link provided in this email.
</#if>
</p> </p>
</section> </section>
</#if> </#if>
@ -40,7 +35,7 @@
<#if deletedAccountCount?? > <#if deletedAccountCount?? >
<section class="account-feedback"> <section class="account-feedback">
<p> <p>
Deleted ${deletedAccountCount} accounts. ${strings.deleted_accounts(deletedAccountCount)}
</p> </p>
</section> </section>
</#if> </#if>
@ -48,7 +43,7 @@
<section id="filter-roles"> <section id="filter-roles">
<form method="POST" action="${formUrls.list}" class="customForm" role="filter by roles"> <form method="POST" action="${formUrls.list}" class="customForm" role="filter by roles">
<select name="roleFilterUri" id="roleFilterUri"> <select name="roleFilterUri" id="roleFilterUri">
<option value="" <#if roleFilterUri = "">selected</#if> >Filter by roles</option> <option value="" <#if roleFilterUri = "">selected</#if> >${strings.filter_by_roles}</option>
<#list roles as role> <#list roles as role>
<option value="${formUrls.list}?roleFilterUri=${role.uri?url}" <#if roleFilterUri = role.uri>selected</#if> >${role.label}</option> <option value="${formUrls.list}?roleFilterUri=${role.uri?url}" <#if roleFilterUri = role.uri>selected</#if> >${role.label}</option>
</#list> </#list>
@ -60,7 +55,7 @@
</select> </select>
<#if roleFilterUri?has_content> <#if roleFilterUri?has_content>
<span><a href="${formUrls.list}" title="view all acounts"> View all accounts</a></span> <span><a href="${formUrls.list}" title="${strings.view_all_accounts_title}">${strings.view_all_accounts}</a></span>
</#if> </#if>
</form> </form>
</section> </section>
@ -68,7 +63,7 @@
<section id="search-accounts"> <section id="search-accounts">
<form method="POST" action="${formUrls.list}" class="customForm" role="search accounts"> <form method="POST" action="${formUrls.list}" class="customForm" role="search accounts">
<input type="text" name="searchTerm" /> <input type="text" name="searchTerm" />
<input class="submit" type="submit" value="Search accounts"/> <input class="submit" type="submit" value="${strings.search_accounts_button}"/>
<!-- <!--
When searchTerm changes, When searchTerm changes,
set pageIndex to 1 set pageIndex to 1
@ -80,64 +75,64 @@
</section> </section>
<#if searchTerm?has_content> <#if searchTerm?has_content>
<section id="search-feedback"> <section id="search-feedback">
<p>Search results for "<strong>${searchTerm}</strong>" | <span><a href="${formUrls.list}" title="view all accounts"> View all accounts</a></span></p> <p>${strings.accounts_search_results} "<strong>${searchTerm}</strong>" | <span><a href="${formUrls.list}" title="${strings.view_all_accounts_title}">${strings.view_all_accounts}</a></span></p>
</section> </section>
</#if> </#if>
<form method="POST" action="${formUrls.list}" id="account-display" class="customForm" role="accounts display"> <form method="POST" action="${formUrls.list}" id="account-display" class="customForm" role="accounts display">
<@p.accountsNav /> <@p.accountsNav />
<table id="account"> <table id="account">
<caption>Account Management</caption> <caption>${strings.account_management}</caption>
<thead> <thead>
<tr> <tr>
<th scope="col"> <input class="delete-all hidden" type="checkbox" name="delete-all"> <th scope="col"> <input class="delete-all hidden" type="checkbox" name="delete-all">
Email Address ${strings.email_address}
<nav class="account-alpha-browse"> <nav class="account-alpha-browse">
<a class="sort-asc" href="?accountsPerPage=${accountsPerPage}&orderField=email&orderDirection=ASC" title="ascending order"></a> <a class="sort-asc" href="?accountsPerPage=${accountsPerPage}&orderField=email&orderDirection=ASC" title="${strings.ascending_order}"></a>
<a class="sort-desc" href="?accountsPerPage=${accountsPerPage}&orderField=email&orderDirection=DESC" title="descending order"></a> <a class="sort-desc" href="?accountsPerPage=${accountsPerPage}&orderField=email&orderDirection=DESC" title="${strings.descending_order}"></a>
</nav> </nav>
</th> </th>
<th scope="col"> <th scope="col">
First name ${strings.first_name}
<nav class="account-alpha-browse"> <nav class="account-alpha-browse">
<a class="sort-asc" href="?accountsPerPage=${accountsPerPage}&orderField=firstName&orderDirection=ASC" title="ascending order"></a> <a class="sort-asc" href="?accountsPerPage=${accountsPerPage}&orderField=firstName&orderDirection=ASC" title="${strings.ascending_order}"></a>
<a class="sort-desc" href="?accountsPerPage=${accountsPerPage}&orderField=firstName&orderDirection=DESC" title="descending order"></a> <a class="sort-desc" href="?accountsPerPage=${accountsPerPage}&orderField=firstName&orderDirection=DESC" title="${strings.descending_order}"></a>
</nav> </nav>
</th> </th>
<th scope="col"> <th scope="col">
Last name ${strings.last_name}
<nav class="account-alpha-browse"> <nav class="account-alpha-browse">
<a class="sort-asc" href="?accountsPerPage=${accountsPerPage}&orderField=lastName&orderDirection=ASC" title="ascending order"></a> <a class="sort-asc" href="?accountsPerPage=${accountsPerPage}&orderField=lastName&orderDirection=ASC" title="${strings.ascending_order}"></a>
<a class="sort-desc" href="?accountsPerPage=${accountsPerPage}&orderField=lastName&orderDirection=DESC" title="descending order"></a> <a class="sort-desc" href="?accountsPerPage=${accountsPerPage}&orderField=lastName&orderDirection=DESC" title="${strings.descending_order}"></a>
</nav> </nav>
</th> </th>
<th scope="col"> <th scope="col">
Status ${strings.status}
<nav class="account-alpha-browse"> <nav class="account-alpha-browse">
<a class="sort-asc" href="?accountsPerPage=${accountsPerPage}&orderField=status&orderDirection=ASC" title="ascending order"></a> <a class="sort-asc" href="?accountsPerPage=${accountsPerPage}&orderField=status&orderDirection=ASC" title="${strings.ascending_order}"></a>
<a class="sort-desc" href="?accountsPerPage=${accountsPerPage}&orderField=status&orderDirection=DESC" title="descending order"></a> <a class="sort-desc" href="?accountsPerPage=${accountsPerPage}&orderField=status&orderDirection=DESC" title="${strings.descending_order}"></a>
</nav> </nav>
</th> </th>
<th scope="col">Roles</th> <th scope="col">${strings.roles}</th>
<th scope="col"> <th scope="col">
Login&nbsp;count ${strings.login_count}
<nav class="account-alpha-browse"> <nav class="account-alpha-browse">
<a class="sort-asc" href="?accountsPerPage=${accountsPerPage}&orderField=count&orderDirection=ASC" title="ascending order"></a> <a class="sort-asc" href="?accountsPerPage=${accountsPerPage}&orderField=count&orderDirection=ASC" title="${strings.ascending_order}"></a>
<a class="sort-desc" href="?accountsPerPage=${accountsPerPage}&orderField=count&orderDirection=DESC" title="descending order"></a> <a class="sort-desc" href="?accountsPerPage=${accountsPerPage}&orderField=count&orderDirection=DESC" title="${strings.descending_order}"></a>
</nav> </nav>
</th> </th>
<th scope="col"> <th scope="col">
Last&nbsp;Login ${strings.last_login}
<nav class="account-alpha-browse"> <nav class="account-alpha-browse">
<a class="sort-asc" href="?accountsPerPage=${accountsPerPage}&orderField=lastLogin&orderDirection=ASC" title="ascending order"></a> <a class="sort-asc" href="?accountsPerPage=${accountsPerPage}&orderField=lastLogin&orderDirection=ASC" title="${strings.ascending_order}"></a>
<a class="sort-desc" href="?accountsPerPage=${accountsPerPage}&orderField=lastLogin&orderDirection=DESC" title="descending order"></a> <a class="sort-desc" href="?accountsPerPage=${accountsPerPage}&orderField=lastLogin&orderDirection=DESC" title="${strings.descending_order}"></a>
</nav> </nav>
</th> </th>
</tr> </tr>
@ -148,7 +143,7 @@
<tr> <tr>
<td> <td>
<#if account.deletable> <#if account.deletable>
<input type="checkbox" name="deleteAccount" value="${account.uri}" title="select this account to delete it"/> <input type="checkbox" name="deleteAccount" value="${account.uri}" title="${strings.select_account_to_delete}"/>
<#assign disableDeleteAccount = '' /> <#assign disableDeleteAccount = '' />
<!-- ignored unless submit action is formUrls.delete --> <!-- ignored unless submit action is formUrls.delete -->
<#else> <#else>
@ -156,7 +151,7 @@
</#if> </#if>
<#if account.editUrl != ""> <#if account.editUrl != "">
<a ${disableDeleteAccount} href="${account.editUrl}" title="click to view account details">${account.emailAddress}</a> <a ${disableDeleteAccount} href="${account.editUrl}" title="${strings.click_to_view_account}">${account.emailAddress}</a>
<!-- when this link is clicked, editAccount is noticed and all other fields are ignored. --> <!-- when this link is clicked, editAccount is noticed and all other fields are ignored. -->
<#else> <#else>
${account.emailAddress} ${account.emailAddress}
@ -185,5 +180,10 @@
<@p.accountsNav /> <@p.accountsNav />
</form> </form>
<script type="text/javascript">
confirm_delete_account_singular = "${strings.confirm_delete_account_singular}"
confirm_delete_account_plural = "${strings.confirm_delete_account_plural}"
</script>
${stylesheets.add('<link rel="stylesheet" href="${urls.base}/css/account/account.css" />')} ${stylesheets.add('<link rel="stylesheet" href="${urls.base}/css/account/account.css" />')}
${scripts.add('<script type="text/javascript" src="${urls.base}/js/account/accountUtils.js"></script>')} ${scripts.add('<script type="text/javascript" src="${urls.base}/js/account/accountUtils.js"></script>')}

View file

@ -2,58 +2,48 @@
<#-- Template for editing a user account --> <#-- Template for editing a user account -->
<h3>My account</h3> <#assign strings = i18n() />
<h3>${strings.myAccount_heading}</h3>
<#if errorEmailIsEmpty??> <#if errorEmailIsEmpty??>
<#assign errorMessage = "You must supply an email address." /> <#assign errorMessage = strings.error_no_email />
</#if> <#elseif errorEmailInUse??>
<#assign errorMessage = strings.error_email_already_exists />
<#if errorEmailInUse??> <#elseif errorEmailInvalidFormat??>
<#assign errorMessage = "An account with that email address already exists." /> <#assign errorMessage = strings.error_invalid_email(emailAddress) />
</#if> <#elseif errorFirstNameIsEmpty??>
<#assign errorMessage = strings.error_no_first_name />
<#if errorEmailInvalidFormat??> <#elseif errorLastNameIsEmpty??>
<#assign errorMessage = "'${emailAddress}' is not a valid email address." /> <#assign errorMessage = strings.error_no_last_name />
</#if> <#elseif errorNoRoleSelected??>
<#assign errorMessage = strings.error_no_role />
<#if errorFirstNameIsEmpty??> <#elseif errorPasswordIsEmpty??>
<#assign errorMessage = "You must supply a first name." /> <#assign errorMessage = strings.error_no_password />
</#if> <#elseif errorPasswordIsWrongLength??>
<#assign errorMessage = strings.error_password_length(minimumLength, maximumLength) />
<#if errorLastNameIsEmpty??> <#elseif errorPasswordsDontMatch??>
<#assign errorMessage = "You must supply a last name." /> <#assign errorMessage = strings.error_password_mismatch />
</#if>
<#if errorPasswordIsEmpty??>
<#assign errorMessage = "No password supplied." />
</#if>
<#if errorPasswordIsWrongLength??>
<#assign errorMessage = "Password must be between ${minimumLength} and ${maximumLength} characters." />
</#if>
<#if errorPasswordsDontMatch??>
<#assign errorMessage = "Passwords do not match." />
</#if> </#if>
<#if errorMessage?has_content> <#if errorMessage?has_content>
<section id="error-alert" role="alert"> <section id="error-alert" role="alert">
<img src="${urls.images}/iconAlert.png" width="24" height="24" alert="Error alert icon"/> <img src="${urls.images}/iconAlert.png" width="24" height="24" alert="${strings.alt_error_alert}" />
<p>${errorMessage}</p> <p>${errorMessage}</p>
</section> </section>
</#if> </#if>
<#if confirmChange??> <#if confirmChange??>
<#assign confirmMessage = "Your changes have been saved." /> <#assign confirmMessage = strings.myAccount_confirm_changes />
</#if> </#if>
<#if confirmEmailSent??> <#if confirmEmailSent??>
<#assign confirmMessage = "Your changes have been saved. A confirmation email has been sent to ${emailAddress}." /> <#assign confirmMessage = strings.myAccount_confirm_changes_plus_note(emailAddress) />
</#if> </#if>
<#if confirmMessage?has_content> <#if confirmMessage?has_content>
<section class="account-feedback" role="alert"> <section class="account-feedback" role="alert">
<p><img class="middle" src="${urls.images}/iconConfirmation.png" alert="Confirmation icon"/> ${confirmMessage}</p> <p><img class="middle" src="${urls.images}/iconConfirmation.png" alt="${strings.alt_confirmation}"/> ${confirmMessage}</p>
</section> </section>
</#if> </#if>
@ -63,30 +53,34 @@
<#include "userAccounts-myProxiesPanel.ftl"> <#include "userAccounts-myProxiesPanel.ftl">
</#if> </#if>
<label for="email-address">Email address<span class="requiredHint"> *</span></label> <label for="email-address">${strings.email_address}<span class="requiredHint"> *</span></label>
<input type="text" name="emailAddress" value="${emailAddress}" id="email-address" role="input" /> <input type="text" name="emailAddress" value="${emailAddress}" id="email-address" role="input" />
<p class="note">Note: if email changes, a confirmation email will<br />be sent to the new email address entered above.</p> <p class="note">${strings.email_change_will_be_confirmed}</p>
<label for="first-name">First name<span class="requiredHint"> *</span></label> <label for="first-name">${strings.first_name}<span class="requiredHint"> *</span></label>
<input type="text" name="firstName" value="${firstName}" id="first-name" role="input" /> <input type="text" name="firstName" value="${firstName}" id="first-name" role="input" />
<label for="last-name">Last name<span class="requiredHint"> *</span></label> <label for="last-name">${strings.last_name}<span class="requiredHint"> *</span></label>
<input type="text" name="lastName" value="${lastName}" id="last-name" role="input" /> <input type="text" name="lastName" value="${lastName}" id="last-name" role="input" />
<#if !externalAuth??> <#if !externalAuth??>
<label for="new-password">New password</label> <label for="new-password">${strings.new_password}</label>
<input type="password" name="newPassword" value="${newPassword}" id="new-password" role="input" /> <input type="password" name="newPassword" value="${newPassword}" id="new-password" role="input" />
<p class="note">Minimum of ${minimumLength} characters in length.<br />If left blank, the password will not be changed.</p> <p class="note">${strings.minimum_password_length(minimumLength)}<br />${strings.leave_password_unchanged}</p>
<label for="confirm-password">Confirm new password</label> <label for="confirm-password">${strings.confirm_password}</label>
<input type="password" name="confirmPassword" value="${confirmPassword}" id="confirm-password" role="input" /> <input type="password" name="confirmPassword" value="${confirmPassword}" id="confirm-password" role="input" />
</#if> </#if>
<p><input type="submit" id="submitMyAccount" name="submitMyAccount" value="Save changes" class="submit" disabled /> or <a class="cancel" href="${urls.referringPage}" title="cancel">Cancel</a></p> <p>
<input type="submit" id="submitMyAccount" name="submitMyAccount" value="${strings.save_changes}" class="submit" disabled />
${strings.or}
<a class="cancel" href="${urls.referringPage}" title="${strings.cancel_title}">${strings.cancel_link}</a>
</p>
<p class="requiredHint">* required fields</p> <p class="requiredHint">* ${strings.required_fields}</p>
</form> </form>
</section> </section>

View file

@ -2,15 +2,21 @@
<#-- Template for setting the account reference field, which can also associate a profile with the user account --> <#-- Template for setting the account reference field, which can also associate a profile with the user account -->
<#assign strings = i18n() />
<section id="edit-myProxy" name="proxyProxiesPanel" role="region"> <section id="edit-myProxy" name="proxyProxiesPanel" role="region">
<h4>Who can edit my profile</h4> <h4>${strings.who_can_edit_profile}</h4>
<label for="addProfileEditor">Add profile editor</label> <label for="addProfileEditor">${strings.add_profile_editor}</label>
<input id="addProfileEditor" type="text" name="proxySelectorAC" class="acSelector" size="35" value="Select an existing last name" role="input" /><span><img class="loading-profileMyAccoount hidden" src="${urls.images}/indicatorWhite.gif" /></span> <input id="addProfileEditor" type="text" name="proxySelectorAC" class="acSelector" size="35"
value="${strings.select_existing_last_name}" role="input" />
<span><img class="loading-profileMyAccoount hidden" src="${urls.images}/indicatorWhite.gif" /></span>
<p class="search-status"><span name='proxySelectorSearchStatus' moreCharsText='type more characters' noMatchText='no match'>&nbsp;</span></p> <p class="search-status">
<span name='proxySelectorSearchStatus' moreCharsText='${strings.type_more_characters}' noMatchText='${strings.no_match}'>&nbsp;</span>
</p>
<p name="excludeUri" style="display: none">${myAccountUri}<p> <p name="excludeUri" style="display: none">${myAccountUri}<p>
<p class="selected-editors">Selected editors:</p> <p class="selected-editors">${strings.selected_editors}:</p>
<#-- Magic ul that holds all of the proxy data and the template that shows how to display it. --> <#-- Magic ul that holds all of the proxy data and the template that shows how to display it. -->
<ul name="proxyData" role="navigation"> <ul name="proxyData" role="navigation">
@ -35,7 +41,7 @@
<p class="proxy-info">%label% | <span class="class-label">%classLabel%</span> <p class="proxy-info">%label% | <span class="class-label">%classLabel%</span>
<br /> <br />
<a class='remove-proxy' href="." templatePart="remove" title="remove selection">Remove selection</a> <a class='remove-proxy' href="." templatePart="remove" title="${strings.remove_selection_title}">${strings.remove_selection}</a>
<input type="hidden" name="proxyUri" value="%uri%" role="input" /> <input type="hidden" name="proxyUri" value="%uri%" role="input" />
</p> </p>

View file

@ -2,42 +2,20 @@
<#-- Confirmation that an password has been created. --> <#-- Confirmation that an password has been created. -->
<#assign subject = "Your ${siteName} password has successfully been created." /> <#assign strings = i18n() />
<#assign html> <#assign subject = strings.password_created_subject(siteName) />
<html>
<head>
<title>${subject}</title>
</head>
<body>
<p>
${userAccount.firstName} ${userAccount.lastName}
</p>
<p> <#assign html = strings.password_created_email_html(siteName,
<strong>Password successfully created.</strong> subject,
</p> userAccount.firstName,
userAccount.lastName,
userAccount.emailAddress) />
<p> <#assign text = strings.password_created_email_text(siteName,
Your new password associated with ${userAccount.emailAddress} has been created. subject,
</p> userAccount.firstName,
userAccount.lastName,
<p> userAccount.emailAddress) />
Thank you.
</p>
</body>
</html>
</#assign>
<#assign text>
${userAccount.firstName} ${userAccount.lastName}
Password successfully created.
Your new password associated with ${userAccount.emailAddress}
has been created.
Thank you.
</#assign>
<@email subject=subject html=html text=text /> <@email subject=subject html=html text=text />

View file

@ -2,42 +2,20 @@
<#-- Confirmation that a password has been reset. --> <#-- Confirmation that a password has been reset. -->
<#assign subject = "Your ${siteName} password changed." /> <#assign strings = i18n() />
<#assign html> <#assign subject = strings.password_reset_complete_subject(siteName) />
<html>
<head>
<title>${subject}</title>
</head>
<body>
<p>
${userAccount.firstName} ${userAccount.lastName}
</p>
<p> <#assign html = strings.password_reset_complete_email_html(siteName,
<strong>Password successfully changed.</strong> subject,
</p> userAccount.firstName,
userAccount.lastName,
userAccount.emailAddress) />
<p> <#assign text = strings.password_reset_complete_email_text(siteName,
Your new password associated with ${userAccount.emailAddress} has been changed. subject,
</p> userAccount.firstName,
userAccount.lastName,
<p> userAccount.emailAddress) />
Thank you.
</p>
</body>
</html>
</#assign>
<#assign text>
${userAccount.firstName} ${userAccount.lastName}
Password successfully changed.
Your new password associated with ${userAccount.emailAddress}
has been changed.
Thank you.
</#assign>
<@email subject=subject html=html text=text /> <@email subject=subject html=html text=text />

View file

@ -2,60 +2,22 @@
<#-- Confirmation email for user account password reset --> <#-- Confirmation email for user account password reset -->
<#assign subject = "${siteName} reset password request" /> <#assign strings = i18n() />
<#assign html> <#assign subject = strings.password_reset_pending_subject(siteName) />
<html>
<head>
<title>${subject}</title>
</head>
<body>
<p>
Dear ${userAccount.firstName} ${userAccount.lastName}:
</p>
<p> <#assign html = strings.password_reset_pending_email_html(siteName,
We have received a request to reset the password for your ${siteName} account (${userAccount.emailAddress}). subject,
</p> userAccount.firstName,
userAccount.lastName,
userAccount.emailAddress,
passwordLink) />
<p> <#assign text = strings.password_reset_pending_email_text(siteName,
Please follow the instructions below to proceed with your password reset. subject,
</p> userAccount.firstName,
userAccount.lastName,
<p> userAccount.emailAddress,
If you did not request this new account you can safely ignore this email. passwordLink) />
This request will expire if not acted upon within 30 days.
</p>
<p>
Click on the link below or paste it into your browser's address bar to reset your password
using our secure server.
</p>
<p>${passwordLink}</p>
<p>Thank you!</p>
</body>
</html>
</#assign>
<#assign text>
Dear ${userAccount.firstName} ${userAccount.lastName}:
We have received a request to reset the password for your ${siteName} account
(${userAccount.emailAddress}).
Please follow the instructions below to proceed with your password reset.
If you did not request this new account you can safely ignore this email.
This request will expire if not acted upon within 30 days.
Paste the link below into your browser's address bar to reset your password
using our secure server.
${passwordLink}
Thank you!
</#assign>
<@email subject=subject html=html text=text /> <@email subject=subject html=html text=text />

View file

@ -2,25 +2,23 @@
<#-- Template for adding a user account --> <#-- Template for adding a user account -->
<h3>Reset your Password</h3> <#assign strings = i18n() />
<p>Please enter your new password for ${userAccount.emailAddress}</p> <h3>${strings.reset_your_password}</h3>
<p>${strings.enter_new_password(userAccount.emailAddress)}</p>
<#if errorPasswordIsEmpty??> <#if errorPasswordIsEmpty??>
<#assign errorMessage = "No password supplied." /> <#assign errorMessage = strings.error_no_password />
</#if> <#elseif errorPasswordIsWrongLength??>
<#assign errorMessage = strings.error_password_length(minimumLength, maximumLength) />
<#if errorPasswordIsWrongLength??> <#elseif errorPasswordsDontMatch??>
<#assign errorMessage = "Password must be between ${minimumLength} and ${maximumLength} characters." /> <#assign errorMessage = strings.error_password_mismatch />
</#if>
<#if errorPasswordsDontMatch??>
<#assign errorMessage = "Passwords do not match." />
</#if> </#if>
<#if errorMessage?has_content> <#if errorMessage?has_content>
<section id="error-alert" role="alert"> <section id="error-alert" role="alert">
<img src="${urls.images}/iconAlert.png" width="24" height="24" alert="Error alert icon"/> <img src="${urls.images}/iconAlert.png" width="24" height="24" alert="${strings.alt_error_alert}"/>
<p>${errorMessage}</p> <p>${errorMessage}</p>
</section> </section>
</#if> </#if>
@ -30,17 +28,17 @@
<input type="hidden" name="user" value="${userAccount.emailAddress}" /> <input type="hidden" name="user" value="${userAccount.emailAddress}" />
<input type="hidden" name="key" value="${userAccount.passwordLinkExpiresHash}" /> <input type="hidden" name="key" value="${userAccount.passwordLinkExpiresHash}" />
<label for="new-password">Password<span class="requiredHint"> *</span></label> <label for="new-password">${strings.new_password}<span class="requiredHint"> *</span></label>
<input type="password" name="newPassword" value="${newPassword}" id="new-password" role="input" /> <input type="password" name="newPassword" value="${newPassword}" id="new-password" role="input" />
<p class="note">Minimum of ${minimumLength} characters in length.</p> <p class="note">${strings.minimum_password_length(minimumLength)}</p>
<label for="confirm-password">Confirm Password<span class="requiredHint"> *</span></label> <label for="confirm-password">${strings.confirm_password}<span class="requiredHint"> *</span></label>
<input type="password" name="confirmPassword" value="${confirmPassword}" id="confirm-password" role="input" /> <input type="password" name="confirmPassword" value="${confirmPassword}" id="confirm-password" role="input" />
<p><input type="submit" name="submit" value="Save changes" class="submit" /></p> <p><input type="submit" name="submit" value="${strings.save_changes}" class="submit"/></p>
<p class="requiredHint">* required fields</p> <p class="requiredHint">* ${strings.required_fields}</p>
</form> </form>
</section> </section>

View file

@ -21,20 +21,22 @@ ${stylesheets.add('<link rel="stylesheet" href="${urls.base}/css/uploadImages.cs
</#macro>--> </#macro>-->
<#assign i18n = i18n() >
<section id="photoCroppingContainer" role="region"> <section id="photoCroppingContainer" role="region">
<h2>Photo Upload</h2> <h2>${i18n.upload_heading}</h2>
<!-- This is the image we're attaching Jcrop to --> <!-- This is the image we're attaching Jcrop to -->
<section id="photoCroppingPreview" role="region"> <section id="photoCroppingPreview" role="region">
<p class="photoCroppingTitleBody">Your profile photo will look like the image below. </p> <p class="photoCroppingTitleBody">${i18n.cropping_caption}</p>
<section class="photoCroppedPreview" role="region"> <section class="photoCroppedPreview" role="region">
<img src="${imageUrl}" id="preview" alt="Image to be cropped"/> <img src="${imageUrl}" id="preview" alt="${i18n.alt_image_to_crop}"/>
</section> </section>
<section id="photoCroppingHowTo" role="region"> <section id="photoCroppingHowTo" role="region">
<p class="photoCroppingNote">To make adjustments, you can drag around and resize the photo to the right. When you are happy with your photo click the "Save Photo" button. </p> <p class="photoCroppingNote">${i18n.cropping_note}</p>
<form id="cropImage" action="${formAction}" method="post" role="form"> <form id="cropImage" action="${formAction}" method="post" role="form">
<!-- Javascript will populate these values --> <!-- Javascript will populate these values -->
@ -43,15 +45,15 @@ ${stylesheets.add('<link rel="stylesheet" href="${urls.base}/css/uploadImages.cs
<input type="hidden" name="w" value="" /> <input type="hidden" name="w" value="" />
<input type="hidden" name="h" value="" /> <input type="hidden" name="h" value="" />
<input class="submit" type="submit" value="Save photo"> <input class="submit" type="submit" value="${i18n.submit_save}">
<span class="or"> or <a class="cancel" href="${cancelUrl}" title="cancel">Cancel</a></span> <span class="or"> ${i18n.or} <a class="cancel" href="${cancelUrl}" title="${i18n.cancel_title}">${i18n.cancel_link}</a></span>
</form> </form>
</section> </section>
</section> </section>
<section id="photoCropping" role="region"> <section id="photoCropping" role="region">
<img src="${imageUrl}" id="cropbox" alt="Preview of photo cropped" /> <img src="${imageUrl}" id="cropbox" alt="${i18n.alt_preview_crop}" />
</section </section
</section> </section>

View file

@ -7,29 +7,35 @@ ${scripts.add('<script type="text/javascript" src="${urls.base}/js/jquery.js"></
${stylesheets.add('<link rel="stylesheet" href="${urls.base}/css/uploadImages.css" />')} ${stylesheets.add('<link rel="stylesheet" href="${urls.base}/css/uploadImages.css" />')}
<#assign i18n = i18n() >
<section id="photoUploadContainer" role="region"> <section id="photoUploadContainer" role="region">
<h2>Photo Upload</h2> <h2>${i18n.upload_heading}</h2>
<#if errorMessage??> <#if errorMessage??>
<section id="error-alert" role="alert"><img src="${urls.images}/iconAlert.png" alt="Error alert icon" /> <section id="error-alert" role="alert"><img src="${urls.images}/iconAlert.png" alt="${i18n.alt_error_alert}" />
<p>${errorMessage}</p> <p>${errorMessage}</p>
</section> </section>
</#if> </#if>
<section id="photoUploadDefaultImage" role="region"> <section id="photoUploadDefaultImage" role="region">
<h3>Current Photo</h3> <h3>${i18n.current_photo}</h3>
<img src="${thumbnailUrl}" width="115" height="115" alt="Individual photo" /> <img src="${thumbnailUrl}" width="115" height="115" alt="${i18n.alt_thumbnail_photo}" />
</section> </section>
<form id="photoUploadForm" action="${formAction}" enctype="multipart/form-data" method="post" role="form"> <form id="photoUploadForm" action="${formAction}" enctype="multipart/form-data" method="post" role="form">
<label>Upload a photo <span> (JPEG, GIF or PNG)</span></label> <label>${i18n.upload_photo} <span>${i18n.photo_types}</span></label>
<input id="datafile" type="file" name="datafile" size="30" /> <input id="datafile" type="file" name="datafile" size="30" />
<p class="note">Maximum file size: ${maxFileSize} megabytes<br /> <p class="note">${i18n.maximum_file_size(maxFileSize)}<br />
Minimum image dimensions: ${thumbnailWidth} x ${thumbnailHeight} pixels</p> ${i18n.minimum_image_dimensions(thumbnailWidth, thumbnailHeight)}</p>
<input class="submit" type="submit" value="Upload photo"/> <input class="submit" type="submit" value="${i18n.submit_upload}"/>
<span class="or"> or <a class="cancel" href="${cancelUrl}" title="cancel">Cancel</a></span> <span class="or"> ${i18n.or} <a class="cancel" href="${cancelUrl}" title="${i18n.cancel_title}">${i18n.cancel_link}</a></span>
</form> </form>
</section> </section>
<script type="text/javascript">
i18n_confirmDelete = ${i18n.confirm_delete}
</script>

View file

@ -7,30 +7,36 @@ ${scripts.add('<script type="text/javascript" src="${urls.base}/js/jquery.js"></
${stylesheets.add('<link rel="stylesheet" href="${urls.base}/css/uploadImages.css" />')} ${stylesheets.add('<link rel="stylesheet" href="${urls.base}/css/uploadImages.css" />')}
<#assign i18n = i18n() >
<section id="photoUpload" role="region"> <section id="photoUpload" role="region">
<h2>Photo Upload</h2> <h2>${i18n.upload_heading}</h2>
<#if errorMessage??> <#if errorMessage??>
<section id="error-alert" role="alert"><img src="${urls.images}/iconAlert.png" alt="Error alert icon" /> <section id="error-alert" role="alert"><img src="${urls.images}/iconAlert.png" alt="${i18n.alt_error_alert}" />
<p>${errorMessage}</p> <p>${errorMessage}</p>
</section> </section>
</#if> </#if>
<section id="photoUploadDefaultImage" role="region"> <section id="photoUploadDefaultImage" role="region">
<h3>Current Photo</h3> <h3>${i18n.current_photo}</h3>
<img src="${thumbnailUrl}" width="115" alt="Individual photo" /> <img src="${thumbnailUrl}" width="115" alt="${i18n.alt_thumbnail_photo}" />
<a class="thumbnail" href="${deleteUrl}">Delete photo</a> <a class="thumbnail" href="${deleteUrl}">${i18n.delete_link}</a>
</section> </section>
<form id="photoUploadForm" action="${formAction}" enctype="multipart/form-data" method="post" role="form"> <form id="photoUploadForm" action="${formAction}" enctype="multipart/form-data" method="post" role="form">
<label>Replace Photo <span> (JPEG, GIF or PNG)</span></label> <label>${i18n.replace_photo} <span>${i18n.photo_types}</span></label>
<input type="file" name="datafile" size="30"> <input type="file" name="datafile" size="30">
<p class="note">Maximum file size: ${maxFileSize} megabytes<br /> <p class="note">${i18n.maximum_file_size(maxFileSize)}<br />
Minimum image dimensions: ${thumbnailWidth}x${thumbnailHeight} pixels</p> ${i18n.minimum_image_dimensions(thumbnailWidth, thumbnailHeight)}</p>
<input class="submit" type="submit" value="Upload photo"> <input class="submit" type="submit" value="${i18n.submit_upload}">
<span class="or"> or <a class="cancel" href="${cancelUrl}" title="cancel">Cancel</a></span> <span class="or"> ${i18n.or} <a class="cancel" href="${cancelUrl}" title="${i18n.cancel_title}">${i18n.cancel_link}</a></span>
</form> </form>
</section> </section>
<script type="text/javascript">
i18n_confirmDelete = "${i18n.confirm_delete}"
</script>

View file

@ -77,3 +77,7 @@ ${headScripts.add('<script type="text/javascript" src="${urls.base}/js/jquery_pl
${scripts.add('<script type="text/javascript" src="${urls.base}/js/imageUpload/imageUploadUtils.js"></script>', ${scripts.add('<script type="text/javascript" src="${urls.base}/js/imageUpload/imageUploadUtils.js"></script>',
'<script type="text/javascript" src="${urls.base}/js/individual/individualUriRdf.js"></script>')} '<script type="text/javascript" src="${urls.base}/js/individual/individualUriRdf.js"></script>')}
<script type="text/javascript">
i18n_confirmDelete = "${i18n().confirm_delete}"
</script>

View file

@ -9,14 +9,12 @@
<#-- This is included by identity.ftl --> <#-- This is included by identity.ftl -->
<#if selectLocale??> <#if selectLocale??>
<li> <li>
<form method="get" action="${selectLocale.selectLocaleUrl}" >
<#list selectLocale.locales as locale> <#list selectLocale.locales as locale>
<button type="submit" name="selection" value="${locale.code}"> <a href="${selectLocale.selectLocaleUrl}?selection=${locale.code}">
<img src="${locale.imageUrl}" height="15" align="middle" alt="${locale.label}"/> <img src="${locale.imageUrl}" height="15" align="middle" alt="${locale.label}"/>
</button> </a>
<#if locale_has_next>|</#if> <#if locale_has_next>|</#if>
</#list> </#list>
</form>
</li> </li>
</#if> </#if>