diff --git a/.gitignore b/.gitignore index 5c48f0e0b97b6d82bf93880858cd51d2db92a22b..8181691a4075c67b187fd3f4c874886167e3b7ea 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,5 @@ /npm-debug.log /resources/static/build /resources/static/production -.DS_Store \ No newline at end of file +.DS_Store +/locale diff --git a/config/aws.json b/config/aws.json index 95eb55fdfae619519adb14a3a8040cd717dcc507..275f067d040c676972be521b66a561e482fe99c5 100644 --- a/config/aws.json +++ b/config/aws.json @@ -12,6 +12,7 @@ "supported_languages": [ "en-US", "it-CH", "db-LB" ], + "debug_lang": "it-CH", "locale_directory": "/home/app/code/locale", "var_path": "/home/app/var", diff --git a/lib/browserid/email_templates/add.ejs b/lib/browserid/email_templates/add.ejs new file mode 100644 index 0000000000000000000000000000000000000000..fb928499b4f11710331a8ae83d7d8b4de035e59a --- /dev/null +++ b/lib/browserid/email_templates/add.ejs @@ -0,0 +1,9 @@ +<%= gettext('Thank you for using Persona.') %> + +<%= format(gettext('Click to confirm this email address and automatically sign in to %s'), [site]) %> +<%= link %> + +<%= format(gettext('Note: If you are NOT trying to sign into this website, please ignore this email.'), [site]) %> + +<%= gettext('Thank you,') %> +<%= gettext('The Persona team') %> diff --git a/lib/browserid/email_templates/new.ejs b/lib/browserid/email_templates/new.ejs new file mode 100644 index 0000000000000000000000000000000000000000..fb928499b4f11710331a8ae83d7d8b4de035e59a --- /dev/null +++ b/lib/browserid/email_templates/new.ejs @@ -0,0 +1,9 @@ +<%= gettext('Thank you for using Persona.') %> + +<%= format(gettext('Click to confirm this email address and automatically sign in to %s'), [site]) %> +<%= link %> + +<%= format(gettext('Note: If you are NOT trying to sign into this website, please ignore this email.'), [site]) %> + +<%= gettext('Thank you,') %> +<%= gettext('The Persona team') %> diff --git a/lib/browserid/email_templates/reset.ejs b/lib/browserid/email_templates/reset.ejs new file mode 100644 index 0000000000000000000000000000000000000000..0b1845507c71c0f4b8b980e680e09f4427cbe53e --- /dev/null +++ b/lib/browserid/email_templates/reset.ejs @@ -0,0 +1,9 @@ +<%= gettext('Forgot your password for Persona? It happens to the best of us.') %> + +<%= gettext('Click to reset your password:') %> +<%= link %> + +<%= gettext('Note: If you did NOT ask to reset your password, please ignore this email.') %> + +<%= gettext('Thank you,') %> +<%= gettext('The Persona team') %> diff --git a/lib/browserid/prove_template.ejs b/lib/browserid/prove_template.ejs deleted file mode 100644 index d20e219da9555171ef51302105a93acec5549179..0000000000000000000000000000000000000000 --- a/lib/browserid/prove_template.ejs +++ /dev/null @@ -1,10 +0,0 @@ -<%= format( - gettext('Thanks for verifying your email address. This message is being sent to you to complete your sign-in to %s.'), [site]) %> - -<%= gettext('Finish registration by clicking this link:') %> <%= link %> - -<%= gettext('If you are NOT trying to sign into this site, just ignore this email.') %> - -<%= gettext('Thanks,') %> -<%= gettext('Persona') %> -<%= gettext('(A better way to sign in)') %> diff --git a/lib/email.js b/lib/email.js index bf83bdc6d77491cd519e4294824b5c92f3b68569..5afe2fe293f1066bc774eef99f52146ae7502c3e 100644 --- a/lib/email.js +++ b/lib/email.js @@ -8,7 +8,8 @@ fs = require('fs'), path = require('path'), ejs = require('ejs'), config = require('./configuration.js'), -logger = require('./logging.js').logger; +logger = require('./logging.js').logger, +url = require('url'); /* if smtp parameters are configured, use them */ try { var smtp_params = config.get('smtp'); } catch(e) {}; @@ -27,8 +28,35 @@ if (smtp_params && smtp_params.host) { } } -const template = ejs.compile( - fs.readFileSync(path.join(__dirname, "browserid", "prove_template.ejs")).toString()); +const TEMPLATE_PATH = path.join(__dirname, "browserid", "email_templates"); + +// the underbar decorator to allow getext to extract strings +function _(str) { return str; } + +// a map of all the different emails we send +const templates = { + "new": { + landing: 'verify_email_address', + subject: _("Confirm email address for Persona"), + template: fs.readFileSync(path.join(TEMPLATE_PATH, 'new.ejs')), + }, + "reset": { + landing: 'verify_email_address', + subject: _("Reset Persona password"), + template: fs.readFileSync(path.join(TEMPLATE_PATH, 'reset.ejs')), + }, + "add": { + landing: 'add_email_address', + subject: _("Confirm email address for Persona"), + template: fs.readFileSync(path.join(TEMPLATE_PATH, 'add.ejs')), + } +}; + +// now turn file contents into compiled templates +Object.keys(templates).forEach(function(type) { + templates[type].template = ejs.compile(templates[type].template.toString()); +}); + var interceptor = undefined; @@ -48,24 +76,36 @@ exports.setInterceptor = function(callback) { }; //TODO send in localeContext -function doSend(landing_page, email, site, secret, langContext) { - var url = config.get('public_url') + "/" + landing_page + "?token=" + encodeURIComponent(secret), - _ = langContext.gettext, +function doSend(email_type, email, site, secret, langContext) { + if (!templates[email_type]) throw "unknown email type: " + email_type; + + // remove scheme from site to make it more human + site = url.parse(site).hostname; + + var email_params = templates[email_type]; + + var public_url = config.get('public_url') + "/" + email_params.landing + "?token=" + encodeURIComponent(secret), + GETTEXT = langContext.gettext, format = langContext.format; if (interceptor) { interceptor(email, site, secret); } else if (config.get('email_to_console')) { // log verification email to console separated by whitespace. - console.log("\nVERIFICATION URL:\n" + url + "\n"); + console.log("\nVERIFICATION URL:\n" + public_url + "\n"); } else { - // TODO(aok) extract_po.sh isn't seeing this string if it's below in object literal - var subject = format(_("Complete Login to %s using Persona"), [site]); emailer.send_mail({ - sender: "Persona@persona.org", + // XXX: Ideally this would be a live email address and a response to these email + // addresses would go into a ticketing system (lloyd/skinny) + sender: "Persona <no-reply@persona.org>", to: email, - subject: subject, - body: template({ link: url, site: site, gettext: _, format: format }) + subject: GETTEXT(email_params.subject), + body: email_params.template({ + link: public_url, + site: site, + gettext: GETTEXT, + format: format + }) }, function(err, success){ if (!success) { logger.error("error sending email to: " + email + " - " + err); @@ -75,9 +115,13 @@ function doSend(landing_page, email, site, secret, langContext) { }; exports.sendNewUserEmail = function(email, site, secret, langContext) { - doSend('verify_email_address', email, site, secret, langContext); + doSend('new', email, site, secret, langContext); }; exports.sendAddAddressEmail = function(email, site, secret, langContext) { - doSend('add_email_address', email, site, secret, langContext); + doSend('add', email, site, secret, langContext); +}; + +exports.sendForgotPasswordEmail = function(email, site, secret, langContext) { + doSend('reset', email, site, secret, langContext); }; diff --git a/resources/static/common/css/style.css b/resources/static/common/css/style.css index dfd8cd6d3bfbeb86b3bf7b3814a612276db5b020..3472f4d621653854c424412ff7a474773fdbf287 100644 --- a/resources/static/common/css/style.css +++ b/resources/static/common/css/style.css @@ -56,8 +56,13 @@ ul, li { list-style-type: none; } -.mono { - font-family: 'Monaco', monospace; +strong { + font-weight: 700; +} + +.hidden { + visibility: hidden; + height: 0; } .tooltip { @@ -134,6 +139,18 @@ input[type=password]:disabled { border-color: #b2b2b2; } +label + input[type=text], +label + input[type=password], +label + input[type=email] { + margin-top: 8px; +} + +label.hidden + input[type=text], +label.hidden + input[type=password], +label.hidden + input[type=email] { + margin-top: 0; +} + input[type=radio], input[type=checkbox] { cursor: pointer; @@ -282,11 +299,30 @@ button.negative:active, box-shadow: 0 0 5px #333 inset; } +.tospp { + line-height: 14px; +} + +.buttonrow { + line-height: 28px; +} + +.buttonrow > .right { + margin-right: 15px; +} + +.buttonrow > .right.emphasize { + margin-right: 0; + margin-top: 8px; +} + +/* .submit #cancel { float: right; margin-right: 15px; line-height: 28px; } +*/ a.secondary[disabled], .submit_disabled a.secondary, .submit_disabled a.secondary:focus, .submit_disabled a.secondary:active { color: #999; @@ -377,14 +413,26 @@ footer .help { background-image: url("/common/i/grain.png"), linear-gradient(top, #dadee1, #c7ccd0); } + /* #wait, #delay { text-align: center; } +*/ +#wait .contents, #error .contents, #delay .contents { + max-width: 430px; + margin: 0 auto; +} +#wait h2, #delay h2 { + font-size: 20px; +} -#wait h2, #error h2, #delay h2 { +#error h2 { font-size: 22px; - margin-bottom: 10px; +} + +#wait p, #error p, #delay p { + margin-top: 20px; } #error .emphasis { @@ -392,7 +440,7 @@ footer .help { color: #aa1401; } -#error_contents { +#error .contents, #wait .contents { max-width: 430px; margin: 0 auto; } @@ -417,7 +465,6 @@ footer .help { .submit { margin-top: 10px; - line-height: 14px; } .submit > p { diff --git a/resources/static/common/js/user.js b/resources/static/common/js/user.js index 95b7c0893c34fd7d36fab3942fa6bc589a6ab36f..be52ee35266f6b908a78941a889ba4200239336c 100644 --- a/resources/static/common/js/user.js +++ b/resources/static/common/js/user.js @@ -160,6 +160,10 @@ BrowserID.User = (function() { throw "invalid email type (should be 'secondary' or 'primary'): " + type; } + function getIdPName(addressInfo) { + return addressInfo.email.replace(/.*@/, ""); + } + /** * Persist an address and key pair locally. * @method persistEmailKeypair @@ -825,6 +829,7 @@ BrowserID.User = (function() { if(info.type === "primary") { User.isUserAuthenticatedToPrimary(email, info, function(authed) { info.authed = authed; + info.idpName = getIdPName(info); complete(info); }, onFailure); } @@ -1224,8 +1229,6 @@ BrowserID.User = (function() { } else { complete(onFailure, "user is not authenticated"); } - - return shouldAsk; } }; diff --git a/resources/static/common/js/wait-messages.js b/resources/static/common/js/wait-messages.js index 00a64aa65609bbe0036a9bda3033220cced2ca87..734239bb9e91e5f25836da3ba117bc32a966fa94 100644 --- a/resources/static/common/js/wait-messages.js +++ b/resources/static/common/js/wait-messages.js @@ -7,7 +7,7 @@ BrowserID.Wait = (function(){ var Wait = { authentication: { title: gettext("Finishing Sign In..."), - message: gettext("In just a moment you'll be signed into BrowserID.") + message: gettext("In just a moment you'll be signed into Persona.") }, generateKey: { @@ -16,8 +16,8 @@ BrowserID.Wait = (function(){ }, slowXHR: { - title: gettext("We are sorry, this request is taking a LOOONG time."), - message: gettext("This message will go away when the request completes (hopefully soon). If you wait too long, close this window and try again."), + title: gettext("We are sorry, this is taking a longer than it should."), + message: gettext("If this doesn't resolve itself within a few seconds, please close the window and try again."), id: "slowXHR" } diff --git a/resources/static/dialog/css/m.css b/resources/static/dialog/css/m.css index ac8b2285240c5f6f43d8bce5d1c9547415d87b1c..40509beb05e94aa7dfa4a385281f9b620b4825f0 100644 --- a/resources/static/dialog/css/m.css +++ b/resources/static/dialog/css/m.css @@ -124,7 +124,7 @@ #selectEmail > .inputs > li > label { margin: 0; - padding: 15px 0; + padding: 8px 0; } #signIn .submit > p { @@ -185,10 +185,6 @@ } - .forgot { - font-size: 16px; - } - .inputs > li { margin-top: 12px; } diff --git a/resources/static/dialog/css/style.css b/resources/static/dialog/css/style.css index 3aa1e6dd335193524e1d94460afd5daaa9cf9488..8e6a7eaf56071cd67f1856944fc699d7ba568c8c 100644 --- a/resources/static/dialog/css/style.css +++ b/resources/static/dialog/css/style.css @@ -12,6 +12,7 @@ body { background-image: url('/common/i/grain.png'), -ms-linear-gradient(top, rgba(113, 126, 137, 0), rgba(113, 126, 137, 0.2)); background-image: url('/common/i/grain.png'), -o-linear-gradient(top, rgba(113, 126, 137, 0), rgba(113, 126, 137, 0.2)); background-image: url('/common/i/grain.png'), linear-gradient(top, rgba(113, 126, 137, 0), rgba(113, 126, 137, 0.2)); + line-height: 18px; } #signIn { @@ -65,6 +66,15 @@ header { background-image: linear-gradient(top, rgba(0,0,0,.05), rgba(0,0,0,0)); } +h2 { + font-size: 20px; +} + +h3 { + font-size: 18px; +} + + .home { width: 161px; height: 40px; @@ -135,6 +145,11 @@ section > .contents { * otherwise the buttons slide right with the arrow */ width: 250px; + font-size: 13px; +} + +.form_section p { + margin-top: 8px; } @@ -241,7 +256,7 @@ section > .contents { #signIn .table { background-color: #eff0f2; - padding: 20px; + padding: 0 20px; } .arrowContainer { @@ -298,7 +313,6 @@ section > .contents { #favicon h2 { margin: 10px 0 0 0; - font-size: 20px; } #favicon h3 { @@ -342,16 +356,8 @@ div#required_email { padding-right: 1px; } -.inputs { - line-height: 18px; -} - .inputs > li { - margin-top: 10px; -} - -.inputs > li:first-child { - margin-top: 0; + margin-top: 8px; } .inputs > li > label { @@ -364,7 +370,7 @@ div#required_email { } #selectEmail > .inputs > li > label { - padding: 6px 1px; + padding: 3px 1px; white-space: nowrap; } @@ -381,10 +387,14 @@ div#required_email { } .submit { + margin-top: 8px; color: #333; font-size: 11px; } +.submit > p { + margin-top: 8px; +} .tospp { font-size: 11px; diff --git a/resources/static/dialog/js/misc/state.js b/resources/static/dialog/js/misc/state.js index dc228b145d1713516c67e615e9d8307266943cf7..65fdc9b0e691806dc8929219fa4acd4b6e9710dd 100644 --- a/resources/static/dialog/js/misc/state.js +++ b/resources/static/dialog/js/misc/state.js @@ -21,6 +21,7 @@ BrowserID.State = (function() { primaryVerificationInfo; function startStateMachine() { + /*jshint validthis: true*/ var self = this, handleState = function(msg, callback) { self.subscribe(msg, function(msg, info) { @@ -44,7 +45,9 @@ BrowserID.State = (function() { handleState("start", function(msg, info) { self.hostname = info.hostname; + self.siteName = info.siteName || info.hostname; self.siteTOSPP = !!(info.privacyPolicy && info.termsOfService); + requiredEmail = info.requiredEmail; startAction(false, "doRPInfo", info); @@ -95,7 +98,11 @@ BrowserID.State = (function() { }); handleState("authenticate", function(msg, info) { - info.siteTOSPP = self.siteTOSPP; + _.extend(info, { + siteName: self.siteName, + siteTOSPP: self.siteTOSPP + }); + startAction("doAuthenticate", info); }); @@ -151,7 +158,12 @@ BrowserID.State = (function() { handleState("user_staged", function(msg, info) { self.stagedEmail = info.email; - info.required = !!requiredEmail; + + _.extend(info, { + required: !!requiredEmail, + siteName: self.siteName + }); + startAction("doConfirmUser", info); }); @@ -209,7 +221,9 @@ BrowserID.State = (function() { // Show the persona TOS/PP only to requiredEmail users who are creating // a new account. - personaTOSPP: requiredEmail && !addPrimaryUser + personaTOSPP: requiredEmail && !addPrimaryUser, + siteName: self.siteName, + idpName: info.idpName || URLParse(info.auth_url).host }); if (primaryVerificationInfo) { @@ -449,7 +463,10 @@ BrowserID.State = (function() { handleState("email_staged", function(msg, info) { self.stagedEmail = info.email; - info.required = !!requiredEmail; + _.extend(info, { + required: !!requiredEmail, + siteName: self.siteName + }); startAction("doConfirmEmail", info); }); diff --git a/resources/static/dialog/js/modules/actions.js b/resources/static/dialog/js/modules/actions.js index 9144b37521a54ad9dae4245493476addd06cde77..fddee337aa73cc653c90d7a4fe6b3b45d252473e 100644 --- a/resources/static/dialog/js/modules/actions.js +++ b/resources/static/dialog/js/modules/actions.js @@ -1,4 +1,4 @@ -/*jshint browser:true, jQuery: true, forin: true, laxbreak:true */ +/*jshint browser:true, jquery: true, forin: true, laxbreak:true */ /*global _: true, BrowserID: true, PageController: true */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -33,13 +33,11 @@ BrowserID.Modules.Actions = (function() { } function startRegCheckService(options, verifier, message, password) { - var controller = startService("check_registration", { - email: options.email, - required: options.required, + var controller = startService("check_registration", _.extend(options, { verifier: verifier, verificationMessage: message, password: password - }); + })); controller.startCheck(); } diff --git a/resources/static/dialog/js/modules/authenticate.js b/resources/static/dialog/js/modules/authenticate.js index d1c13818901917c5ae93120aa100ce0cc6e579c8..24ea77b11e8acf28ef98b6af66c62dd200061e56 100644 --- a/resources/static/dialog/js/modules/authenticate.js +++ b/resources/static/dialog/js/modules/authenticate.js @@ -1,4 +1,4 @@ -/*jshint browser:true, jQuery: true, forin: true, laxbreak:true */ +/*jshint browser:true, jquery: true, forin: true, laxbreak:true */ /*global BrowserID:true, PageController: true */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -25,6 +25,7 @@ BrowserID.Modules.Authenticate = (function() { } function initialState(info) { + /*jshint validthis: true*/ var self=this; self.submit = checkEmail; @@ -39,6 +40,7 @@ BrowserID.Modules.Authenticate = (function() { } function checkEmail(info) { + /*jshint validthis: true*/ var email = getEmail(), self = this; @@ -70,6 +72,7 @@ BrowserID.Modules.Authenticate = (function() { } function createSecondaryUser(callback) { + /*jshint validthis: true*/ var self=this, email = getEmail(); @@ -81,6 +84,7 @@ BrowserID.Modules.Authenticate = (function() { } function authenticate() { + /*jshint validthis: true*/ var email = getEmail(), pass = helpers.getAndValidatePassword("#password"), self = this; @@ -114,6 +118,7 @@ BrowserID.Modules.Authenticate = (function() { } function enterEmailState() { + /*jshint validthis: true*/ if (!dom.is("#email", ":disabled")) { this.submit = checkEmail; showHint("start"); @@ -121,6 +126,7 @@ BrowserID.Modules.Authenticate = (function() { } function enterPasswordState(callback) { + /*jshint validthis: true*/ var self=this; dom.setInner("#password", ""); @@ -136,6 +142,7 @@ BrowserID.Modules.Authenticate = (function() { } function forgotPassword() { + /*jshint validthis: true*/ var email = getEmail(); if (email) { var info = addressInfo || { email: email }; @@ -144,6 +151,7 @@ BrowserID.Modules.Authenticate = (function() { } function emailKeyUp() { + /*jshint validthis: true*/ var newEmail = dom.getInner("#email"); if (newEmail !== lastEmail) { lastEmail = newEmail; @@ -160,7 +168,7 @@ BrowserID.Modules.Authenticate = (function() { var self=this; self.renderDialog("authenticate", { - sitename: user.getHostname(), + siteName: options.siteName, email: lastEmail }); diff --git a/resources/static/dialog/js/modules/check_registration.js b/resources/static/dialog/js/modules/check_registration.js index efd38e246b6c7ee4c19515f46c5720679949a6c9..784298ac2e6e584b289e869a35028a5077381065 100644 --- a/resources/static/dialog/js/modules/check_registration.js +++ b/resources/static/dialog/js/modules/check_registration.js @@ -15,9 +15,12 @@ BrowserID.Modules.CheckRegistration = (function() { start: function(options) { var self=this; options = options || {}; - options.required = !!options.required; - - self.renderWait("confirm_email", options); + var templateData = { + email: options.email, + required: options.required, + siteName: options.siteName + }; + self.renderWait("confirm_email", templateData); self.email = options.email; self.verifier = options.verifier; diff --git a/resources/static/dialog/js/modules/pick_email.js b/resources/static/dialog/js/modules/pick_email.js index c28a23babeeefe78540ac346f93f96e5212894b1..8b35cab2348cd3fc9b33dc101e6e21012c6879cd 100644 --- a/resources/static/dialog/js/modules/pick_email.js +++ b/resources/static/dialog/js/modules/pick_email.js @@ -93,7 +93,7 @@ BrowserID.Modules.PickEmail = (function() { self.renderDialog("pick_email", { identities: identities, - siteemail: user.getOriginEmail() + siteEmail: user.getOriginEmail() }); if (options.siteTOSPP) { diff --git a/resources/static/dialog/js/modules/provision_primary_user.js b/resources/static/dialog/js/modules/provision_primary_user.js index 367195e4a0191f0054288f801d04534d4362a014..4e1c9e186a70e900eb697d631c8d8dddef8a57bd 100644 --- a/resources/static/dialog/js/modules/provision_primary_user.js +++ b/resources/static/dialog/js/modules/provision_primary_user.js @@ -29,7 +29,9 @@ BrowserID.Modules.ProvisionPrimaryUser = (function() { case "primary.verify": self.close("primary_user_unauthenticated", { email: email, - auth_url: auth + auth_url: auth, + // XXX use self.addressInfo universally. + idpName: self.addressInfo.idpName }); complete(true); break; @@ -55,19 +57,15 @@ BrowserID.Modules.ProvisionPrimaryUser = (function() { throw "missing config option: email"; } - if(!(auth && prov)) { - user.addressInfo(email, function(status) { - if(status.type === "primary") { - provisionPrimaryUser.call(self, email, status.auth, status.prov); - } - else { - self.renderError("error", { action: errors.provisioningBadPrimary }); - } - }, self.getErrorDialog(errors.isEmailRegistered)); - } - else { - provisionPrimaryUser.call(self, email, auth, prov); - } + user.addressInfo(email, function(status) { + self.addressInfo = status; + if(status.type === "primary") { + provisionPrimaryUser.call(self, email, status.auth, status.prov); + } + else { + self.renderError("error", { action: errors.provisioningBadPrimary }); + } + }, self.getErrorDialog(errors.isEmailRegistered)); ProvisionPrimaryUser.sc.start.call(self, options); diff --git a/resources/static/dialog/js/modules/set_password.js b/resources/static/dialog/js/modules/set_password.js index 02c6de1038dd03df26c63c2dc377a9708e8af66f..d1d3025767450ebc66e5ce570494b7e717544e09 100644 --- a/resources/static/dialog/js/modules/set_password.js +++ b/resources/static/dialog/js/modules/set_password.js @@ -1,4 +1,4 @@ -/*jshint browser:true, jQuery: true, forin: true, laxbreak:true */ +/*jshint browser:true, jquery: true, forin: true, laxbreak:true */ /*global _: true, BrowserID: true, PageController: true */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -13,6 +13,7 @@ BrowserID.Modules.SetPassword = (function() { sc; function submit(callback) { + /*jshint validthis: true*/ var pass = dom.getInner("#password"), vpass = dom.getInner("#vpassword"), options = this.options; @@ -26,6 +27,7 @@ BrowserID.Modules.SetPassword = (function() { } function cancel() { + /*jshint validthis: true*/ this.close("cancel_state"); } @@ -35,6 +37,7 @@ BrowserID.Modules.SetPassword = (function() { options = options || {}; self.renderDialog("set_password", { + email: options.email, password_reset: !!options.password_reset, cancelable: options.cancelable !== false, personaTOSPP: options.personaTOSPP diff --git a/resources/static/dialog/js/modules/verify_primary_user.js b/resources/static/dialog/js/modules/verify_primary_user.js index 8a35914e2665c6a07d5814f439da440e5699a752..c7cd90b83ce8a769d0985722fd582cab65b733e7 100644 --- a/resources/static/dialog/js/modules/verify_primary_user.js +++ b/resources/static/dialog/js/modules/verify_primary_user.js @@ -27,7 +27,7 @@ BrowserID.Modules.VerifyPrimaryUser = (function() { }); var url = helpers.toURL(auth_url, {email: email}); - + win.document.location = url; complete(callback); @@ -52,7 +52,9 @@ BrowserID.Modules.VerifyPrimaryUser = (function() { email: data.email, auth_url: data.auth_url, requiredEmail: data.requiredEmail || false, - personaTOSPP: data.personaTOSPP + personaTOSPP: data.personaTOSPP, + siteName: data.siteName, + idpName: data.idpName }); if (data.siteTOSPP) { diff --git a/resources/static/dialog/views/add_email.ejs b/resources/static/dialog/views/add_email.ejs index 15ebbad134b0779d228dc3f5cbb9102a1193fa2f..c702bd5ac7d85e959aba351332ce254bc4d01322 100644 --- a/resources/static/dialog/views/add_email.ejs +++ b/resources/static/dialog/views/add_email.ejs @@ -2,14 +2,12 @@ - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - <strong><%= gettext('Sign in using') %></strong> - <div id="addEmail" class="cf form_section"> <ul class="inputs"> <li> - <label for="newEmail"><%= gettext('New email address') %></label> - <input id="newEmail" name="newEmail" type="email" autocapitalize="off" autocorrect="off" maxlength="254" <% if (typeof email !== "undefined") { %> value="<%= email %>" <% } %>/> + <label for="newEmail"><%= gettext('Add another email address to your Persona password.') %></label> + <input id="newEmail" name="newEmail" type="email" autocapitalize="off" autocorrect="off" maxlength="254" <% if (typeof email !== "undefined") { %> value="<%= email %>" <% } %> placeholder="<%= gettext("email address") %>"/> <div id="email_format" class="tooltip" for="newEmail"> <%= gettext('This field must be an email address.') %> @@ -29,14 +27,14 @@ </li> <li id="hint_section" class="addressInfo"> - <%= gettext("Please hold on while we get information about your email provider.") %> + <%= gettext("Checking with your email provider.") %> </li> </ul> - <div class="submit cf"> - <button id="addNewEmail"><%= gettext('add') %></button> - <a href="#" id="cancel" class="action"><%= gettext('cancel') %></a> - </div> + <p class="submit cf buttonrow"> + <button id="addNewEmail"><%= gettext('add') %></button> + <a href="#" id="cancel" class="right"><%= gettext('cancel') %></a> + </p> </div> diff --git a/resources/static/dialog/views/authenticate.ejs b/resources/static/dialog/views/authenticate.ejs index a95c45b441638b50424e8ca14dc1dc21df6fa421..8fac82a6afa7507939539cc50064b14b4dfe0ad5 100644 --- a/resources/static/dialog/views/authenticate.ejs +++ b/resources/static/dialog/views/authenticate.ejs @@ -1,13 +1,18 @@ <% /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ %> - <strong><%= gettext('Sign in using') %></strong> + <div class="form_section"> + <p class="start"> + <%= format(gettext('%s uses Persona instead of usernames to sign you in.'), ["<strong>" + siteName +"</strong>"]) %> + + </p> + <ul class="inputs"> <li> - <label for="email"><%= gettext('Email') %></label> - <input id="email" type="email" autocapitalize="off" autocorrect="off" value="<%= email %>" maxlength="254" tabindex="1"/> + <label for="email"><%= gettext('To sign in with Persona, please enter your email address.') %></label> + <input id="email" type="email" autocapitalize="off" autocorrect="off" value="<%= email %>" maxlength="254" tabindex="1" placeholder="<%= gettext('enter email address') %>"/> <div id="email_format" class="tooltip" for="email"> <%= gettext('This field must be an email address.') %> @@ -20,53 +25,44 @@ <div id="could_not_add" class="tooltip" for="email"> <%= gettext('We just sent an email to that address! If you really want to send another, wait a minute or two and try again.') %> </div> - - <div id="already_registered" class="tooltip" for="email"> - That email address is already registered! You should try again. - </div> </li> - <li id="hint_section" class="start"> - <%= format(gettext('Enter your email address to sign in to <strong>%s</strong>'), [sitename]) %> - </li> - - <li id="hint_section" class="addressInfo"> - <%= gettext("Please hold on while we get information about your email provider.") %> + <li id="hint_section" class="addressInfo submit"> + <%= gettext("Checking with your email provider.") %> </li> <li class="returning"> - <a id="forgotPassword" class="forgot right" href="#" tabindex="4"><%= gettext('forgot your password?') %></a> - <label for="password"><%= gettext('Password') %></label> + <label for="password" class="hidden"><%= gettext('Password') %></label> - <input id="password" type="password" maxlength="80" tabindex="2" /> + <input id="password" type="password" maxlength="80" tabindex="2" placeholder="<%= gettext('password') %>" /> <div id="password_required" class="tooltip" for="password"> <%= gettext('The password field is required.') %> </div> <div id="cannot_authenticate" class="tooltip" for="password"> - <%= gettext('The account cannot be logged in with this username and password.') %> + <%= gettext('This email address and password do not match.') %> </div> </li> </ul> - <div class="submit cf"> - <p class="cf"> - <button class="start addressInfo" tabindex="3"><%= gettext('next') %></button> - <button class="returning" tabindex="3"><%= gettext('sign in') %></button> - </p> - - <p class="tospp"> - <%= format( - gettext('By proceeding, you agree to %s\'s <a %s>Terms</a> and <a %s>Privacy Policy</a>.'), - [ "Persona", - ' href="https://login.persona.org/tos" target="_new"', - ' href="https://login.persona.org/privacy" target="_new"', - ]) %> - </p> - - </div> + <p class="submit cf buttonrow"> + <button class="start addressInfo"><%= gettext('next') %></button> + <button class="returning"><%= gettext('sign in') %></button> + <a id="forgotPassword" class="returning" href="#"><%= gettext('Forgot your password?') %></a> + </p> + + + <p class="submit tospp"> + <%= format( + gettext('By proceeding, you agree to %s\'s <a %s>Terms</a> and <a %s>Privacy Policy</a>.'), + [ "Persona", + ' href="https://login.persona.org/tos" target="_new"', + ' href="https://login.persona.org/privacy" target="_new"', + ]) %> + </p> + </div> diff --git a/resources/static/dialog/views/confirm_email.ejs b/resources/static/dialog/views/confirm_email.ejs index 01ab935ed3d7b5206b7ae244bf4eec9cda20fa44..380b051ef47b8db3368807163de78aaa99174a3f 100644 --- a/resources/static/dialog/views/confirm_email.ejs +++ b/resources/static/dialog/views/confirm_email.ejs @@ -2,22 +2,13 @@ License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ %> - <h2><%= gettext('Check your email!') %></h2> + <h2><%= gettext('Confirm your email address') %></h2> <p> - <%= format(gettext('We sent a confirmation email to <strong>%s</strong>'), [email]) %> + <%= format(gettext('Check your email at %s.'), ["<strong>" + email + "</strong>"]) %> </p> <p> - <%= gettext('To finish signing in just click the verify link we sent to your email address.') %> - </p> - <br /> - - <p> - <% if(required) { %> - <%= format(gettext('If this is a mistake, just ignore the sent email and <a %s>cancel</a>.'), [' href="#" id="back"']) %> - <% } else { %> - <%= format(gettext('If this is a mistake, just ignore the sent email and <a %s>use another email address</a>.'), [' href="#" id="back"']) %> - <% } %> + <%= format(gettext('Click the link in the confirmation email. You\'ll then immediately be signed in to %s.'), ["<strong>" + siteName + "</strong>"]) %> </p> diff --git a/resources/static/dialog/views/is_this_your_computer.ejs b/resources/static/dialog/views/is_this_your_computer.ejs index 52fa24c45eb1889e1c4376c4aab387d5eb49b02d..c359518caf82feb178f294aa205378ec86c52d78 100644 --- a/resources/static/dialog/views/is_this_your_computer.ejs +++ b/resources/static/dialog/views/is_this_your_computer.ejs @@ -3,19 +3,20 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/. */ %> <div id="your_computer_content"> - <h2><%= gettext('If you don\'t mind me asking, is this your computer?') %></h2> - + <h2><%= gettext('Remember You?') %></h2> + <p><%= gettext('How long would you like to remain signed in with Persona?') %></p> <ul> <li> - <button id="this_is_my_computer" tabindex="3"><%= gettext('yes') %></button> - <%= gettext('If so, we\'ll keep you logged in for two weeks.') %> + <button id="this_is_my_computer" tabindex="3"><%= gettext('One month') %></button> + <%= gettext('I trust this computer.') %> </li> <li> - <button id="this_is_not_my_computer" class="negative" tabindex="3"><%= gettext('no') %></button> - <%= gettext('If you\'re at a public computer such as a library or internet cafe, choose this. We\'ll prompt you for your password in an hour for greater security.') %> + <button id="this_is_not_my_computer" class="negative" tabindex="3"><%= gettext('This session only') %></button> + <%= gettext('This is not my computer.') %> </li> </ul> + <p><%= gettext('Note: You can of course sign out of Persona at any time.') %></p> </div> diff --git a/resources/static/dialog/views/pick_email.ejs b/resources/static/dialog/views/pick_email.ejs index 059072425b93d6be854125b4290d444f26c019ad..244d801fa400c6b33ffceba5c354a34e595a66d9 100644 --- a/resources/static/dialog/views/pick_email.ejs +++ b/resources/static/dialog/views/pick_email.ejs @@ -3,28 +3,30 @@ - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - <strong><%= gettext('Sign in using') %></strong> + + <p> + <%= gettext('Sign in as...') %> + </p> <div id="selectEmail" class="form_section"> <ul class="inputs"> <% _.each(identities, function(item, index) { var emailAddress = item.address, id = "email_" + index; %> <li> - <label for="<%= id %>" class="serif<% if (emailAddress === siteemail) { %> preselected<% } %> selectable" title="<%= emailAddress %>" > + <label for="<%= id %>" class="<% if (emailAddress === siteEmail) { %> preselected<% } %> selectable" title="<%= emailAddress %>" > <input type="radio" name="email" id="<%= id %>" value="<%= emailAddress %>" - <% if (emailAddress === siteemail) { %> checked="checked" <% } %> + <% if (emailAddress === siteEmail) { %> checked="checked" <% } %> /> <%= emailAddress %> </label> </li> <% }); %> </ul> - <a id="useNewEmail" class="emphasize" href="#"><%= gettext('Add another email') %></a> - <a id="thisIsNotMe" class="emphasize" href="#"><%= gettext('This is not me...') %></a> + + <a id="useNewEmail" class="emphasize" href="#"><%= gettext('Add another email address') %></a> + <a id="thisIsNotMe" class="emphasize" href="#"><%= gettext('This is not me') %></a> - <div class="submit add cf"> - <p class="cf"> - <button id="signInButton"><%= gettext('sign in') %></button> - </p> - </div> + <p class="submit add cf"> + <button id="signInButton"><%= gettext('sign in') %></button> + </p> </div> diff --git a/resources/static/dialog/views/required_email.ejs b/resources/static/dialog/views/required_email.ejs index 5245319c2e48ee6849561757f1a8d9b7b9e7ef83..973048b7b76c981361cecc74d161dfbc7897ae14 100644 --- a/resources/static/dialog/views/required_email.ejs +++ b/resources/static/dialog/views/required_email.ejs @@ -41,7 +41,7 @@ </div> <div id="cannot_authenticate" class="tooltip" for="password"> - <%= gettext("The account cannot be logged in with this username and password.") %> + <%= gettext('This email address and password do not match.') %> </div> </li> diff --git a/resources/static/dialog/views/set_password.ejs b/resources/static/dialog/views/set_password.ejs index c16a1f2d9fc6378601fde28faeefe159cbb416e5..8f08142034da05352c7c7e28531913562497405a 100644 --- a/resources/static/dialog/views/set_password.ejs +++ b/resources/static/dialog/views/set_password.ejs @@ -2,22 +2,28 @@ - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - <strong><%= gettext('Welcome to Persona!') %></strong> - <div class="form_section" id="set_password"> + <% if (password_reset) { %> + <strong><%= gettext("Reset your password") %></strong> + <% } %> + <ul class="inputs"> <li> - <% if(password_reset || !cancelable) { %> - <%= gettext("Choose a new password you'll use when you sign in with Persona.") %> - <% } else { %> - <%= gettext("Next, choose a new password you'll use when you sign in with Persona.") %> + <% if (!password_reset) { %> + <%= gettext("Your email address is new to us. Please create a password to use with Persona.") %> <% } %> </li> <li> - <label for="password"><%= gettext('Password') %></label> - <input id="password" type="password" maxlength="80" /> + + <% if (password_reset) { %> + <label for="password"><%= format(gettext("Create a new password to use with %s."), ["Persona"]) %></label> + <% } else { %> + <label for="password"><%= format(gettext("%s"), ["<strong>" + email + "</strong>"]) %></label> + <% } %> + + <input id="password" type="password" maxlength="80" placeholder="<%= gettext("create password") %>"/> <div class="tooltip" id="password_required" for="password"> <%= gettext('Password is required.') %> @@ -33,38 +39,44 @@ </li> <li> - <label for="vpassword"><%= gettext('Verify Password') %></label> - <input id="vpassword" placeholder="<%= gettext('Repeat Password') %>" type="password" maxlength=80 /> + <label for="vpassword" class="hidden"><%= gettext('Verify Password') %></label> + <input id="vpassword" placeholder="<%= gettext('verify password') %>" type="password" maxlength="80" /> <div class="tooltip" id="vpassword_required" for="vpassword"> <%= gettext('Verification password is required.') %> </div> <div class="tooltip" id="passwords_no_match" for="vpassword"> - <%= gettext('Passwords do not match.') %> + <%= gettext('These passwords don\'t match!') %> </div> </li> </ul> - <div class="submit cf"> - <p class="cf"> + <p class="submit cf buttonrow"> <button id="<%= password_reset ? "password_reset" : "verify_user" %>"> - <%= password_reset ? gettext('reset password') : gettext('verify email') %> + <%= gettext(password_reset ? 'reset password' : 'done') %> </button> + <% if(cancelable) { %> - <a id="cancel" class="action" href="#"><%= gettext('cancel') %></a> + <a id="cancel" class="right" href="#"><%= gettext('cancel') %></a> <% } %> + </p> + + <% if (password_reset) { %> + <p class="submit"> + <%= gettext("Note: This password will be used with all of your Persona email addresses.") %> + </p> + <% } %> + + <% if (personaTOSPP) { %> + <p id="persona_tospp" class="submit tospp"> + <%= format( + gettext('By proceeding, you agree to %s\'s <a %s>Terms</a> and <a %s>Privacy Policy</a>.'), + [ "Persona", + ' href="https://login.persona.org/tos" target="_new"', + ' href="https://login.persona.org/privacy" target="_new"', + ]) %> </p> - <% if (personaTOSPP) { %> - <p id="persona_tospp" class="tospp"> - <%= format( - gettext('By proceeding, you agree to %s\'s <a %s>Terms</a> and <a %s>Privacy Policy</a>.'), - [ "Persona", - ' href="https://login.persona.org/tos" target="_new"', - ' href="https://login.persona.org/privacy" target="_new"', - ]) %> - </p> - <% } %> - </div> + <% } %> </div> diff --git a/resources/static/dialog/views/verify_primary_user.ejs b/resources/static/dialog/views/verify_primary_user.ejs index c2d4da92de3cdeb7a34d18a1be6a242a1823f370..d186d200fba22a1067e2f469d5cd712ed409c848 100644 --- a/resources/static/dialog/views/verify_primary_user.ejs +++ b/resources/static/dialog/views/verify_primary_user.ejs @@ -2,73 +2,31 @@ - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> -<% if (requiredEmail) { %> - <strong><%= gettext('The site requested you sign in using') %></strong> - <div id="verify_primary_user" class="cf form_section"> - <ul class="inputs"> - - <li> - <label for="email"><%= gettext('Email') %></label> - <input id="required_email" type="email" value="<%= email %>" disabled /> - <div id="could_not_add" class="tooltip" for="required_email"> - <%= gettext("We just sent an email to that address! If you really want to send another, wait a minute or two and try again.") %> - </div> - </li> - - <li class="small"> - <%= gettext("You must sign in with your email provider to verify ownership of this address. This window will be redirected to") %> - <p> - <strong><%= auth_url %></strong>. - </p> - </li> - </ul> - - <div class="submit cf"> - <p class="cf"> - <button id="verifyWithPrimary"><%= gettext("verify") %></button> - </p> - - <% if (personaTOSPP) { %> - <p id="persona_tospp" class="tospp"> - <%= format( - gettext('By proceeding, you agree to %s\'s <a %s>Terms</a> and <a %s>Privacy Policy</a>.'), - [ "Persona", - ' href="https://login.persona.org/tos" target="_new"', - ' href="https://login.persona.org/privacy" target="_new"', - ]) %> - </p> - <% } %> - </div> - </div> - -<% } else { %> - <strong><%= gettext("Verify With Email Provider") %></strong> - - <div id="verify_primary_user" class="cf form_section"> - <div class="small"> - <%= gettext("You must sign in with your email provider to verify ownership of this address. This window will be redirected to") %> - <p> - <strong><%= auth_url %></strong>. +<div class="cf form_section"> + <h3> + <%= format(gettext("%s makes this easy"), [idpName]) %> + </h3> + + <p> + <%= format(gettext("Persona lets you use your %s account to sign into sites like %s."), [idpName, siteName]) %> + </p> + <p> + <%= format(gettext("Once you verify your account there, you will be signed in to %s."), [siteName]) %> + </p> + <p class="submit cf buttonrow"> + <button id="verifyWithPrimary"><%= format(gettext("sign in with %s"), [idpName]) %></button> + <a href="#" id="cancel" class="emphasize right"><%= gettext("Use a different email address") %></a> + </p> + + <% if (personaTOSPP) { %> + <p id="persona_tospp" class="submit tospp"> + <%= format( + gettext('By proceeding, you agree to %s\'s <a %s>Terms</a> and <a %s>Privacy Policy</a>.'), + [ "Persona", + ' href="https://login.persona.org/tos" target="_new"', + ' href="https://login.persona.org/privacy" target="_new"', + ]) %> </p> - </div> - - <div class="submit cf"> - <p class="cf"> - <button id="verifyWithPrimary"><%= gettext("verify") %></button> - <a href="#" id="cancel" class="action"><%= gettext("cancel") %></a> - </p> - <% if (personaTOSPP) { %> - <p id="persona_tospp" class="tospp"> - <%= format( - gettext('By proceeding, you agree to %s\'s <a %s>Terms</a> and <a %s>Privacy Policy</a>.'), - [ "Persona", - ' href="https://login.persona.org/tos" target="_new"', - ' href="https://login.persona.org/privacy" target="_new"', - ]) %> - </p> - <% } %> - </div> - - </div> -<% } %> + <% } %> +</div> diff --git a/resources/static/test/cases/common/js/user.js b/resources/static/test/cases/common/js/user.js index 26813f1815568a5b5626606aeedabed04e7ae751..271fa30d0f502bba33494653bb99f41297f3c2c4 100644 --- a/resources/static/test/cases/common/js/user.js +++ b/resources/static/test/cases/common/js/user.js @@ -1152,6 +1152,7 @@ var jwcrypto = require("./lib/jwcrypto"); equal(info.type, "primary", "correct type"); equal(info.email, "registered@testuser.com", "correct email"); equal(info.authed, true, "user is authenticated with IdP"); + equal(info.idpName, "testuser.com", "unknown IdP, use email host portion for name"); start(); }, testHelpers.unexpectedFailure diff --git a/resources/views/dialog.ejs b/resources/views/dialog.ejs index 9bf2250be9fd1a0834b44c4843125e54fe8f2c7e..9da0ca5f249e676e5f012313fd4c2fb0a9328684 100644 --- a/resources/views/dialog.ejs +++ b/resources/views/dialog.ejs @@ -12,9 +12,7 @@ <div id="signIn"> <div class="table"> - <div class="vertical"> - <div class="contents"> - </div> + <div class="vertical contents"> </div> </div> <div class="arrowContainer"> @@ -28,23 +26,28 @@ <section id="wait"> <!-- because each section is an absolutely positioned element, we have to use the inner table container element to be able to vertically/horizontally center correctly. Without the table element, the layout gets all messed up. --> <div class="table"> - <div class="vertical contents"> - <h2><%= gettext('Communicating with server') %></h2> - <p><%= gettext('Just a moment while we talk with the server.') %></p> + <div class="vertical"> + <div class="contents"> + <h2 class="center"><%= gettext('Connecting to Persona...') %></h2> + </div> </div> </div> </section> <section id="error"> <div class="table"> - <div class="vertical contents"> + <div class="vertical"> + <div class="contents"> + </div> </div> </div> </section> <section id="delay"> <div class="table"> - <div class="vertical contents"> + <div class="vertical"> + <div class="contents"> + </div> </div> </div> </section> diff --git a/resources/views/dialog_layout.ejs b/resources/views/dialog_layout.ejs index 954d9bfa5cff4c3e009f8f032aecad4e300f52d7..5eb03bdb09f21243b7c674d4099eee8486ffd2e7 100644 --- a/resources/views/dialog_layout.ejs +++ b/resources/views/dialog_layout.ejs @@ -31,7 +31,7 @@ </div> <footer> -<%- format(gettext('Mozilla Persona is the fast and secure way to sign in. <a %s>Learn more →</a>'), [" href='/about' target='_blank'"]) %> +<%- format(gettext('<strong>Persona.</strong> Simplified sign-in, built by a non-profit. <a %s>Learn more→</a>'), [" href='/about' target='_blank'"]) %> </footer> diff --git a/resources/views/forgot.ejs b/resources/views/forgot.ejs index 369ef504aefe55627d3a83216fb11b13dee532f4..87b0d8f7b4f853feeb6ffd4cdbd1f64ef3d7ad71 100644 --- a/resources/views/forgot.ejs +++ b/resources/views/forgot.ejs @@ -72,7 +72,7 @@ </div> <div class="tooltip" id="passwords_no_match" for="vpassword"> - Passwords do not match. + These passwords don't match! </div> </li> diff --git a/resources/views/signin.ejs b/resources/views/signin.ejs index a0ed5a5fc8300f55d29493db7f345dd0bf23f23e..d09e2a56e3ad317ced53ac1e9547dcf606433900 100644 --- a/resources/views/signin.ejs +++ b/resources/views/signin.ejs @@ -42,7 +42,8 @@ </div> <div id="cannot_authenticate" class="tooltip" for="password"> - The account cannot be logged in with this username and password. + This email address and password do not match. + </div> </li> </ul> diff --git a/resources/views/signup.ejs b/resources/views/signup.ejs index 9e92bd83b6e5be5865af429ece9f1b226ddd9cb6..81ec178b4280f3f1394062c80d9574f04e00dad5 100644 --- a/resources/views/signup.ejs +++ b/resources/views/signup.ejs @@ -75,7 +75,7 @@ </div> <div class="tooltip" id="passwords_no_match" for="vpassword"> - Passwords do not match. + These passwords don't match! </div> </li> diff --git a/scripts/awsbox/post_deploy.js b/scripts/awsbox/post_deploy.js index af133aa60c7652b91cdc1bf66b2a616af507a92c..a8e56f72a4795cfa944337506894cb9cdaa524a8 100755 --- a/scripts/awsbox/post_deploy.js +++ b/scripts/awsbox/post_deploy.js @@ -10,7 +10,20 @@ fi echo ">> updating strings" svn co -q http://svn.mozilla.org/projects/l10n-misc/trunk/browserid/locale +cd locale +svn up +cd .. +./scripts/extract_po.sh locale/ +# yuck! our debug language breaks if this is not present +for file in locale/templates/LC_MESSAGES/*.pot ; do + mv $file $file.old + sed 's/CHARSET/UTF-8/g' $file.old > $file + rm -f $file.old +done + +./scripts/merge_po.sh locale/ ./locale/compile-mo.sh locale/ +./locale/compile-json.sh locale/ resources/static/i18n/ echo ">> generating production resources" scripts/compress