-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Add globalization #2407
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add globalization #2407
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,6 +7,8 @@ | |
| * Module Dependencies. | ||
| */ | ||
|
|
||
| var g = require('strong-globalize')(); | ||
|
|
||
| var loopback = require('../../lib/loopback'); | ||
| var utils = require('../../lib/utils'); | ||
| var path = require('path'); | ||
|
|
@@ -203,22 +205,22 @@ module.exports = function(User) { | |
| realmDelimiter); | ||
|
|
||
| if (realmRequired && !query.realm) { | ||
| var err1 = new Error('realm is required'); | ||
| var err1 = new Error(g.f('realm is required')); | ||
| err1.statusCode = 400; | ||
| err1.code = 'REALM_REQUIRED'; | ||
| fn(err1); | ||
| return fn.promise; | ||
| } | ||
| if (!query.email && !query.username) { | ||
| var err2 = new Error('username or email is required'); | ||
| var err2 = new Error(g.f('{{username}} or {{email}} is required')); | ||
| err2.statusCode = 400; | ||
| err2.code = 'USERNAME_EMAIL_REQUIRED'; | ||
| fn(err2); | ||
| return fn.promise; | ||
| } | ||
|
|
||
| self.findOne({ where: query }, function(err, user) { | ||
| var defaultError = new Error('login failed'); | ||
| var defaultError = new Error(g.f('login failed')); | ||
| defaultError.statusCode = 401; | ||
| defaultError.code = 'LOGIN_FAILED'; | ||
|
|
||
|
|
@@ -248,7 +250,7 @@ module.exports = function(User) { | |
| if (self.settings.emailVerificationRequired && !user.emailVerified) { | ||
| // Fail to log in if email verification is not done yet | ||
| debug('User email has not been verified'); | ||
| err = new Error('login failed as the email has not been verified'); | ||
| err = new Error(g.f('login failed as the email has not been verified')); | ||
| err.statusCode = 401; | ||
| err.code = 'LOGIN_FAILED_EMAIL_NOT_VERIFIED'; | ||
| fn(err); | ||
|
|
@@ -295,7 +297,7 @@ module.exports = function(User) { | |
| } else if (accessToken) { | ||
| accessToken.destroy(fn); | ||
| } else { | ||
| fn(new Error('could not find accessToken')); | ||
| fn(new Error(g.f('could not find {{accessToken}}'))); | ||
| } | ||
| }); | ||
| return fn.promise; | ||
|
|
@@ -446,15 +448,21 @@ module.exports = function(User) { | |
|
|
||
| options.text = options.text.replace(/\{href\}/g, options.verifyHref); | ||
|
|
||
| options.text = g.f(options.text); | ||
|
|
||
| options.to = options.to || user.email; | ||
|
|
||
| options.subject = options.subject || 'Thanks for Registering'; | ||
|
|
||
| options.subject = g.f(options.subject); | ||
|
|
||
| options.headers = options.headers || {}; | ||
|
|
||
| var template = loopback.template(options.template); | ||
| options.html = template(options); | ||
|
|
||
| options.html = g.f(options.html); | ||
|
|
||
| Email.send(options, function(err, email) { | ||
| if (err) { | ||
| fn(err); | ||
|
|
@@ -510,11 +518,11 @@ module.exports = function(User) { | |
| }); | ||
| } else { | ||
| if (user) { | ||
| err = new Error('Invalid token: ' + token); | ||
| err = new Error(g.f('Invalid token: %s', token)); | ||
| err.statusCode = 400; | ||
| err.code = 'INVALID_TOKEN'; | ||
| } else { | ||
| err = new Error('User not found: ' + uid); | ||
| err = new Error(g.f('User not found: %s', uid)); | ||
| err.statusCode = 404; | ||
| err.code = 'USER_NOT_FOUND'; | ||
| } | ||
|
|
@@ -543,7 +551,7 @@ module.exports = function(User) { | |
|
|
||
| options = options || {}; | ||
| if (typeof options.email !== 'string') { | ||
| var err = new Error('Email is required'); | ||
| var err = new Error(g.f('Email is required')); | ||
| err.statusCode = 400; | ||
| err.code = 'EMAIL_REQUIRED'; | ||
| cb(err); | ||
|
|
@@ -555,7 +563,7 @@ module.exports = function(User) { | |
| return cb(err); | ||
| } | ||
| if (!user) { | ||
| err = new Error('Email not found'); | ||
| err = new Error(g.f('Email not found')); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. {{Email}} |
||
| err.statusCode = 404; | ||
| err.code = 'EMAIL_NOT_FOUND'; | ||
| return cb(err); | ||
|
|
@@ -591,7 +599,7 @@ module.exports = function(User) { | |
| if (typeof plain === 'string' && plain) { | ||
| return true; | ||
| } | ||
| var err = new Error('Invalid password: ' + plain); | ||
| var err = new Error(g.f('Invalid password: %s', plain)); | ||
| err.statusCode = 422; | ||
| throw err; | ||
| }; | ||
|
|
@@ -650,20 +658,21 @@ module.exports = function(User) { | |
| UserModel.remoteMethod( | ||
| 'login', | ||
| { | ||
| description: 'Login a user with username/email and password.', | ||
| description: g.f('Login a user with username/email and password.'), | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. {{username/email}} or {{username}}/{{email}} |
||
| accepts: [ | ||
| { arg: 'credentials', type: 'object', required: true, http: { source: 'body' }}, | ||
| { arg: 'include', type: ['string'], http: { source: 'query' }, | ||
| description: 'Related objects to include in the response. ' + | ||
| 'See the description of return value for more details.' }, | ||
| description: g.f('Related objects to include in the response. ' + | ||
| 'See the description of return value for more details.') }, | ||
| ], | ||
| returns: { | ||
| arg: 'accessToken', type: 'object', root: true, | ||
| description: | ||
| 'The response body contains properties of the AccessToken created on login.\n' + | ||
| g.f('The response body contains properties of the {{AccessToken}} created on login.\n' + | ||
| 'Depending on the value of `include` parameter, the body may contain ' + | ||
| 'additional properties:\n\n' + | ||
| ' - `user` - `{User}` - Data of the currently logged in user. (`include=user`)\n\n', | ||
| ' - `user` - `U+007BUserU+007D` - Data of the currently logged in user. ' + | ||
| '{{(`include=user`)}}\n\n'), | ||
| }, | ||
| http: { verb: 'post' }, | ||
| } | ||
|
|
@@ -672,16 +681,16 @@ module.exports = function(User) { | |
| UserModel.remoteMethod( | ||
| 'logout', | ||
| { | ||
| description: 'Logout a user with access token.', | ||
| description: g.f('Logout a user with access token.'), | ||
| accepts: [ | ||
| { arg: 'access_token', type: 'string', required: true, http: function(ctx) { | ||
| var req = ctx && ctx.req; | ||
| var accessToken = req && req.accessToken; | ||
| var tokenID = accessToken && accessToken.id; | ||
|
|
||
| return tokenID; | ||
| }, description: 'Do not supply this argument, it is automatically extracted ' + | ||
| 'from request headers.', | ||
| }, description: g.f('Do not supply this argument, it is automatically extracted ' + | ||
| 'from request headers.'), | ||
| }, | ||
| ], | ||
| http: { verb: 'all' }, | ||
|
|
@@ -691,7 +700,7 @@ module.exports = function(User) { | |
| UserModel.remoteMethod( | ||
| 'confirm', | ||
| { | ||
| description: 'Confirm a user registration with email verification token.', | ||
| description: g.f('Confirm a user registration with email verification token.'), | ||
| accepts: [ | ||
| { arg: 'uid', type: 'string', required: true }, | ||
| { arg: 'token', type: 'string', required: true }, | ||
|
|
@@ -704,7 +713,7 @@ module.exports = function(User) { | |
| UserModel.remoteMethod( | ||
| 'resetPassword', | ||
| { | ||
| description: 'Reset password for a user with email.', | ||
| description: g.f('Reset password for a user with email.'), | ||
| accepts: [ | ||
| { arg: 'options', type: 'object', required: true, http: { source: 'body' }}, | ||
| ], | ||
|
|
@@ -715,7 +724,7 @@ module.exports = function(User) { | |
| UserModel.afterRemote('confirm', function(ctx, inst, next) { | ||
| if (ctx.args.redirect !== undefined) { | ||
| if (!ctx.res) { | ||
| return next(new Error('The transport does not support HTTP redirects.')); | ||
| return next(new Error(g.f('The transport does not support HTTP redirects.'))); | ||
| } | ||
| ctx.res.location(ctx.args.redirect); | ||
| ctx.res.status(302); | ||
|
|
@@ -733,7 +742,7 @@ module.exports = function(User) { | |
| // email validation regex | ||
| var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; | ||
|
|
||
| UserModel.validatesFormatOf('email', { with: re, message: 'Must provide a valid email' }); | ||
| UserModel.validatesFormatOf('email', { with: re, message: g.f('Must provide a valid email') }); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Regexp is one of the challenges for globalization. In short, it does not work because the word order in sentences varies from language to language. This case requires careful refactoring.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The message option is just the error string returned if the regex fails, it is not part of the regex. |
||
|
|
||
| // FIXME: We need to add support for uniqueness of composite keys in juggler | ||
| if (!(UserModel.settings.realmRequired || UserModel.settings.realmDelimiter)) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,6 +3,8 @@ | |
| // This file is licensed under the MIT License. | ||
| // License text available at https://opensource.org/licenses/MIT | ||
|
|
||
| var g = require('strong-globalize')(); | ||
|
|
||
| var models = require('../../lib/models'); | ||
|
|
||
| var loopback = require('../../'); | ||
|
|
@@ -37,15 +39,15 @@ var data = { pushSettings: [ | |
| ] }; | ||
|
|
||
| Application.create(data, function(err, data) { | ||
| console.log('Created: ', data.toObject()); | ||
| g.log('Created: %s', data.toObject()); | ||
| }); | ||
|
|
||
|
|
||
| Application.register('rfeng', 'MyApp', { description: 'My first mobile application' }, | ||
| Application.register('rfeng', 'MyApp', { description: g.f('My first mobile application') }, | ||
| function(err, result) { | ||
| console.log(result.toObject()); | ||
|
|
||
| result.resetKeys(function(err, result) { | ||
| console.log(result.toObject()); | ||
| g.log(result.toObject()); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need to use |
||
| }); | ||
| }); | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
space between
\nand%sThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was no space there to begin with.
Also,
descwill be displayed on a new line.