Add globalization

This commit is contained in:
Candy 2016-06-07 10:48:28 -04:00
parent de0f51b664
commit b52a7217a9
20 changed files with 306 additions and 142 deletions

View File

@ -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')();
module.exports = function(loopback) {
loopback.getCurrentContext = function() {
return null;
@ -10,6 +12,6 @@ module.exports = function(loopback) {
loopback.runInContext =
loopback.createContext = function() {
throw new Error('Current context is not supported in the browser.');
throw new Error(g.f('Current context is not supported in the browser.'));
};
};

View File

@ -7,6 +7,8 @@
* Module Dependencies.
*/
var g = require('strong-globalize')();
var loopback = require('../../lib/loopback');
var assert = require('assert');
var uid = require('uid2');
@ -111,7 +113,7 @@ module.exports = function(AccessToken) {
} else if (isValid) {
cb(null, token);
} else {
var e = new Error('Invalid Access Token');
var e = new Error(g.f('Invalid Access Token'));
e.status = e.statusCode = 401;
e.code = 'INVALID_TOKEN';
cb(e);

View File

@ -36,6 +36,8 @@
*/
var g = require('strong-globalize')();
var loopback = require('../../lib/loopback');
var async = require('async');
var assert = require('assert');
@ -536,7 +538,7 @@ module.exports = function(ACL) {
break;
default:
process.nextTick(function() {
var err = new Error('Invalid principal type: ' + type);
var err = new Error(g.f('Invalid principal type: %s', type));
err.statusCode = 400;
cb(err);
});

View File

@ -7,6 +7,8 @@
* Module Dependencies.
*/
var g = require('strong-globalize')();
var PersistedModel = require('../../lib/loopback').PersistedModel;
var loopback = require('../../lib/loopback');
var utils = require('../../lib/utils');
@ -110,7 +112,7 @@ module.exports = function(Change) {
})
.join('\n');
var msg = 'Cannot rectify ' + modelName + ' changes:\n' + desc;
var msg = g.f('Cannot rectify %s changes:\n%s', modelName, desc);
err = new Error(msg);
err.details = { errors: errors };
return callback(err);

View File

@ -15,6 +15,8 @@
* @inherits {Model}
*/
var g = require('strong-globalize')();
module.exports = function(Email) {
/**
* Send an email with the given `options`.
@ -43,13 +45,13 @@ module.exports = function(Email) {
*/
Email.send = function() {
throw new Error('You must connect the Email Model to a Mail connector');
throw new Error(g.f('You must connect the {{Email}} Model to a {{Mail}} connector'));
};
/**
* A shortcut for Email.send(this).
*/
Email.prototype.send = function() {
throw new Error('You must connect the Email Model to a Mail connector');
throw new Error(g.f('You must connect the {{Email}} Model to a {{Mail}} connector'));
};
};

View File

@ -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,14 +205,14 @@ 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);
@ -218,7 +220,7 @@ module.exports = function(User) {
}
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'));
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.'),
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,7 +681,7 @@ 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;
@ -680,8 +689,8 @@ module.exports = function(User) {
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') });
// FIXME: We need to add support for uniqueness of composite keys in juggler
if (!(UserModel.settings.realmRequired || UserModel.settings.realmDelimiter)) {

View File

@ -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 loopback = require('../../');
var client = loopback();
var CartItem = require('./models').CartItem;
@ -16,10 +18,10 @@ CartItem.attachTo(remote);
// call the remote method
CartItem.sum(1, function(err, total) {
console.log('result:', err || total);
g.log('result:%s', err || total);
});
// call a built in remote method
CartItem.find(function(err, items) {
console.log(items);
g.log(items);
});

View File

@ -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 loopback = require('../../');
var app = loopback();
@ -22,4 +24,4 @@ Color.create({ name: 'blue' });
app.listen(3000);
console.log('a list of colors is available at http://localhost:3000/colors');
g.log('a list of colors is available at {{http://localhost:3000/colors}}');

View File

@ -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 loopback = require('../../');
var app = loopback();
@ -22,7 +24,7 @@ var Color = loopback.createModel('color', { 'name': String });
Color.beforeRemote('**', function(ctx, unused, next) {
// Inside LoopBack code, you can read the property from the context
var ns = loopback.getCurrentContext();
console.log('Request to host', ns && ns.get('host'));
g.log('Request to host %s', ns && ns.get('host'));
next();
});
@ -30,5 +32,5 @@ app.dataSource('db', { connector: 'memory' });
app.model(Color, { dataSource: 'db' });
app.listen(3000, function() {
console.log('A list of colors is available at http://localhost:3000/colors');
g.log('A list of colors is available at {{http://localhost:3000/colors}}');
});

View File

@ -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());
});
});

View File

@ -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 loopback = require('../../');
var app = loopback();
@ -25,4 +27,4 @@ Color.all(function() {
app.listen(3000);
console.log('a list of colors is available at http://localhost:3000/colors');
g.log('a list of colors is available at {{http://localhost:3000/colors}}');

View File

@ -3,6 +3,9 @@
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
var SG = require('strong-globalize');
SG.SetRootDir(__dirname, {autonomousMsgLoading: 'all'});
/**
* loopback ~ public api
*/

112
intl/en/messages.json Normal file
View File

@ -0,0 +1,112 @@
{
"3b46d3a780fd6ae5f95ade489a0efffe": "Current context is not supported in the browser.",
"7e0fca41d098607e1c9aa353c67e0fa1": "Invalid Access Token",
"320c482401afa1207c04343ab162e803": "Invalid principal type: {0}",
"c2b5d51f007178170ca3952d59640ca4": "Cannot rectify {0} changes:\n{1}",
"b2aa64e3b5aa234388d0b457f3ba995a": "You must connect the Email Model to a Mail connector",
"0caffe1d763c8cca6a61814abe33b776": "Email is required",
"1b2a6076dccbe91a56f1672eb3b8598c": "The response body contains properties of the {{AccessToken}} created on login.\nDepending on the value of `include` parameter, the body may contain additional properties:\n\n - `user` - `U+007BUserU+007D` - Data of the currently logged in user. {{(`include=user`)}}\n\n",
"2362ba55796c733e337af169922327a2": "Related objects to include in the response. See the description of return value for more details.",
"306999d39387d87b2638199ff0bed8ad": "Reset password for a user with email.",
"39f25db6c2d9cb0c11d9c46ef6bd3402": "username or email is required",
"3aae63bb7e8e046641767571c1591441": "login failed as the email has not been verified",
"3caaa84fc103d6d5612173ae6d43b245": "Invalid token: {0}",
"42e3fa18945255412ebc6561e2c6f1dc": "Confirm a user registration with email verification token.",
"430b6326d7ebf6600a39f614ef516bc8": "Do not supply this argument, it is automatically extracted from request headers.",
"44a6c8b1ded4ed653d19ddeaaf89a606": "Email not found",
"5e81ad3847a290dc650b47618b9cbc7e": "login failed",
"83cfabbe3aa84ce52e0f5ed7c3b2e9b3": "Login a user with username/email and password.",
"8608c28f5e6df0008266e3c497836176": "Logout a user with access token.",
"860d1a0b8bd340411fb32baa72867989": "The transport does not support HTTP redirects.",
"a50d10fc6e0959b220e085454c40381e": "User not found: {0}",
"a9ce058e495aba6f1aa3e041bfc1035b": "could not find accessToken",
"ad24a933c0351aa6fc39c8f1431b0ee4": "realm is required",
"c68a93f0a9524fed4ff64372fc90c55f": "Must provide a valid email",
"f58cdc481540cd1f69a4aa4da2e37981": "Invalid password: {0}",
"f0bd73df8714cefb925e3b8da2f4c5f6": "result:{0}",
"10e01c895dc0b2fecc385f9f462f1ca6": "a list of colors is available at {{http://localhost:3000/colors}}",
"8a27e0c9ce3ebf0e0c3978efb456e13e": "Request to host {0}",
"a40684f5a9f546115258b76938d1de37": "A list of colors is available at {{http://localhost:3000/colors}}",
"1e85f822b547a75d7d385048030e4ecb": "Created: {0}",
"7d5e7ed0efaedf3f55f380caae0df8b8": "My first mobile application",
"04bd8af876f001ceaf443aad6a9002f9": "Authentication requires model {0} to be defined.",
"095afbf2f1f0e5be678f5dac5c54e717": "Access Denied",
"2d3071e3b18681c80a090dc0efbdb349": "could not find {0} with id {1}",
"316e5b82c203cf3de31a449ee07d0650": "Expected boolean, got {0}",
"57b87ae0e65f6ab7a2e3e6cbdfca49a4": "Cannot create data source {0}: {1}",
"62e933dca3cbd369087f706db669e881": "{{`app.boot`}} was removed, use the new module loopback-boot instead",
"7e287fc885d9fdcf42da3a12f38572c1": "Authorization Required",
"1d7833c3ca2f05fdad8fad7537531c40": "\t SUBJECT:{0}",
"275f22ab95671f095640ca99194b7635": "\t FROM:{0}",
"3d63008ccfb2af1db2142e8cc2716ace": "Warning: No email transport specified for sending email. Setup a transport to send mail messages.",
"4a4f04a4e480fc5d4ee73b84d9a4b904": "Sending Mail:",
"63a091ced88001ab6acb58f61ec041c5": "\t TEXT:{0}",
"93ba9a1d03da3b7696332d3f155c5bb7": "\t HTML:{0}",
"ecb06666ef95e5db27a5ac1d6a17923b": "\t TO:{0}",
"f0aed00a3d3d0b97d6594e4b70e0c201": "\t TRANSPORT:{0}",
"0da38687fed24275c1547e815914a8e3": "Delete a related item by id for {0}.",
"22fe62fa8d595b72c62208beddaa2a56": "Update a related item by id for {0}.",
"528325f3cbf1b0ab9a08447515daac9a": "Update {0} of this model.",
"543d19bad5e47ee1e9eb8af688e857b4": "Foreign key for {0}.",
"598ff0255ffd1d1b71e8de55dbe2c034": "Check the existence of {0} relation to an item by id.",
"5a36cc6ba0cc27c754f6c5ed6015ea3c": "Remove the {0} relation to an item by id.",
"61e5deebaf44d68f4e6a508f30cc31a3": "Relation `{0}` does not exist for model `{1}`",
"651f0b3cbba001635152ec3d3d954d0a": "Find a related item by id for {0}.",
"7bc7b301ad9c4fc873029d57fb9740fe": "Queries {0} of {1}.",
"7c837b88fd0e509bd3fc722d7ddf0711": "Foreign key for {0}",
"830cb6c862f8f364e9064cea0026f701": "Fetches hasOne relation {0}.",
"855ecd4a64885ba272d782435f72a4d4": "Unknown \"{0}\" id \"{1}\".",
"86254879d01a60826a851066987703f2": "Add a related item by id for {0}.",
"8ae418c605b6a45f2651be9b1677c180": "Invalid remote method: `{0}`",
"9442a303f4c26de8e29e39430f03d63a": "could not find a model with id {0}",
"c0057a569ff9d3b509bac61a4b2f605d": "Deletes all {0} of this model.",
"d6f43b266533b04d442bdb3955622592": "Creates a new instance in {0} of this model.",
"da13d3cdf21330557254670dddd8c5c7": "Counts {0} of {1}.",
"ec296bb6191b3eb43570e250ab4ba919": "must specify an id or data",
"f66ae3cf379b2fce28575a3282defe1a": "Deletes {0} of this model.",
"03f79fa268fe199de2ce4345515431c1": "No change record found for {0} with id {1}",
"0f1c71f74b040bfbe8d384a414e31f03": "Get a set of deltas and conflicts since the given checkpoint.",
"15254dec061d023d6c030083a0cef50f": "Create a new instance of the model and persist it into the data source.",
"16a11368d55b85a209fc6aea69ee5f7a": "Delete all matching records.",
"1bc1d489ddf347af47af3d9b1fc7cc15": "Run multiple updates at once. Note: this is not atomic.",
"1bc7d8283c9abda512692925c8d8e3c0": "Get the current checkpoint.",
"1caa7cc61266e7aef7db7d2f0e27ac3e": "Update the properties of the most recent change record kept for this instance.",
"2a7df74fe6e8462e617b79d5fbb536ea": "Get the most recent change record for this instance.",
"2a9684b3d5b3b67af74bac74eb1b0843": "Find all instances of the model matched by filter from the data source.",
"2e406dbfed4c5eaeff9d3daaa366c69e": "Find a model instance by id from the data source.",
"2e50838caf0c927735eb15d12866bdd7": "Get the changes to a model since a given checkpoint.Provide a filter object to reduce the number of results returned.",
"4203ab415ec66a78d3164345439ba76e": "Cannot call {0}.{1}(). The {2} method has not been setup. The {{PersistedModel}} has not been correctly attached to a {{DataSource}}!",
"51ea9b6245bb5e672b236d640ca3b048": "An object of Change property name/value pairs",
"55ddedd4c501348f82cb89db02ec85c1": "An object of model property name/value pairs",
"62e8b0a733417978bab22c8dacf5d7e6": "Cannot apply bulk updates, the connector does not correctly report the number of updated records.",
"6329e0ac1de3c250ebb1df5afd5a2a7b": "The number of instances updated",
"6bc376432cd9972cf991aad3de371e78": "Missing data for change: {0}",
"7f2fde7f0f860ead224b11ba8d75aa1c": "Create an update list from a delta list.",
"829160747cbc802e29d8cd45c68e7dba": "Patch attributes for a model instance and persist it into the data source.",
"8bab6720ecc58ec6412358c858a53484": "Bulk update failed, the connector has modified unexpected number of records: {0}",
"a98b6cc6547706b5c6bffde0ed5fd55c": "Find first instance of the model matched by filter from the data source.",
"aada86412c03def85d98b75e4d786edc": "Patch an existing model instance or insert a new one into the data source.",
"c46d4aba1f14809c16730faa46933495": "Filter defining fields and include",
"c65600640f206f585d300b4bcb699d95": "Create a checkpoint.",
"d32cbcec1c7022d9a975699865ff6036": "Delete a model instance by id from the data source.",
"dcb6261868ff0a7b928aa215b07d068c": "Create a change stream.",
"e43e320a435ec1fa07648c1da0d558a7": "Check whether a model instance exists in the data source.",
"e92aa25b6b864e3454b65a7c422bd114": "Bulk update failed, the connector has deleted unexpected number of records: {0}",
"ea63d226b6968e328bdf6876010786b5": "Cannot apply bulk updates, the connector does not correctly report the number of deleted records.",
"f04c62976db4b2b6c8bf907087b53996": "Update instances of the model matched by where from the data source.",
"f1d4ac54357cc0932f385d56814ba7e4": "Conflict",
"f37d94653793e33f4203e45b4a1cf106": "Count instances of the model matched by where from the data source.",
"0e21aad369dd09e1965c11949303cefd": "Remoting metadata for {0}.{1} {{\"isStatic\"}} does not match new method name-based style.",
"2e110abee2c95bcfc2dafd48be7e2095": "Cannot configure {0}: {{config.dataSource}} must be an instance of {{DataSource}}",
"3438fab56cc7ab92dfd88f0497e523e0": "The relations property of `{0}` configuration must be an object",
"3591f1d3e115b46f9f195df5ca548a6a": "Model not found: model `{0}` is extending an unknown model `{1}`.",
"42a36bac5cf03c4418d664500c81047a": "{{DataSource}} option {{\"defaultForType\"}} is no longer supported",
"734a7bebb65e10899935126ba63dd51f": "The options property of `{0}` configuration must be an object",
"779467f467862836e19f494a37d6ab77": "The acls property of `{0}` configuration must be an array of objects",
"80a32e80cbed65eba2103201a7c94710": "Model not found: {0}",
"83cbdc2560ba9f09155ccfc63e08f1a1": "Property `{0}` cannot be reconfigured for `{1}`",
"97795efe0c3eb7f35ce8cf8cfe70682b": "The configuration of `{0}` is missing {{`dataSource`}} property.\nUse `null` or `false` to mark models not attached to any data source.",
"c61a5a02ba3801a892308f70f5d55a14": "Remoting metadata {{\"isStatic\"}} is deprecated. Please specify {{\"prototype.name\"}} in method name instead for {{isStatic=false}}.",
"dc568bee32deb0f6eaf63e73b20e8ceb": "Ignoring non-object \"methods\" setting of \"{0}\".",
"cb6b65cca90372e428100fd21f8b2259": "Unknown middleware phase {0}"
}

View File

@ -7,6 +7,8 @@
* Module dependencies.
*/
var g = require('strong-globalize')();
var DataSource = require('loopback-datasource-juggler').DataSource;
var Registry = require('./registry');
var assert = require('assert');
@ -237,8 +239,8 @@ app.dataSource = function(name, config) {
return ds;
} catch (err) {
if (err.message) {
err.message = 'Cannot create data source ' + JSON.stringify(name) +
': ' + err.message;
err.message = g.f('Cannot create data source %s: %s',
JSON.stringify(name), err.message);
}
throw err;
}
@ -322,7 +324,7 @@ app.enableAuth = function(options) {
var Model = app.registry.findModel(m);
if (!Model) {
throw new Error(
'Authentication requires model ' + m + ' to be defined.');
g.f('Authentication requires model %s to be defined.', m));
}
if (m.dataSource || m.app) return;
@ -377,15 +379,15 @@ app.enableAuth = function(options) {
} else {
var messages = {
403: {
message: 'Access Denied',
message: g.f('Access Denied'),
code: 'ACCESS_DENIED',
},
404: {
message: ('could not find ' + modelName + ' with id ' + modelId),
message: (g.f('could not find %s with id %s', modelName, modelId)),
code: 'MODEL_NOT_FOUND',
},
401: {
message: 'Authorization Required',
message: g.f('Authorization Required'),
code: 'AUTHORIZATION_REQUIRED',
},
};
@ -407,7 +409,7 @@ app.enableAuth = function(options) {
app.boot = function(options) {
throw new Error(
'`app.boot` was removed, use the new module loopback-boot instead');
g.f('{{`app.boot`}} was removed, use the new module loopback-boot instead'));
};
function dataSourcesFromConfig(name, config, connectorRegistry, registry) {
@ -485,7 +487,7 @@ function setSharedMethodSharedProperties(model, app, modelConfigs) {
var settingValue = settings[setting];
var settingValueType = typeof settingValue;
if (settingValueType !== 'boolean')
throw new TypeError('Expected boolean, got ' + settingValueType);
throw new TypeError(g.f('Expected boolean, got %s', settingValueType));
});
// set sharedMethod.shared using the merged settings

View File

@ -7,6 +7,8 @@
* Dependencies.
*/
var g = require('strong-globalize')();
var mailer = require('nodemailer');
var assert = require('assert');
var debug = require('debug')('loopback:connector:mail');
@ -148,15 +150,15 @@ Mailer.send = function(options, fn) {
}
if (debug.enabled || settings && settings.debug) {
console.log('Sending Mail:');
g.log('Sending Mail:');
if (options.transport) {
console.log('\t TRANSPORT:', options.transport);
console.log(g.f('\t TRANSPORT:%s', options.transport));
}
console.log('\t TO:', options.to);
console.log('\t FROM:', options.from);
console.log('\t SUBJECT:', options.subject);
console.log('\t TEXT:', options.text);
console.log('\t HTML:', options.html);
g.log('\t TO:%s', options.to);
g.log('\t FROM:%s', options.from);
g.log('\t SUBJECT:%s', options.subject);
g.log('\t TEXT:%s', options.text);
g.log('\t HTML:%s', options.html);
}
if (transport) {
@ -164,7 +166,7 @@ Mailer.send = function(options, fn) {
'You must supply an Email.settings.transports containing a valid transport');
transport.sendMail(options, fn);
} else {
console.warn('Warning: No email transport specified for sending email.' +
g.warn('Warning: No email transport specified for sending email.' +
' Setup a transport to send mail messages.');
process.nextTick(function() {
fn(null, options);

View File

@ -6,6 +6,9 @@
/*!
* Module Dependencies.
*/
var g = require('strong-globalize')();
var assert = require('assert');
var RemoteObjects = require('strong-remoting');
var SharedClass = require('strong-remoting').SharedClass;
@ -167,14 +170,14 @@ module.exports = function(registry) {
} else if (model) {
fn(null, model);
} else {
err = new Error('could not find a model with id ' + id);
err = new Error(g.f('could not find a model with id %s', id));
err.statusCode = 404;
err.code = 'MODEL_NOT_FOUND';
fn(err);
}
});
} else {
fn(new Error('must specify an id or data'));
fn(new Error(g.f('must specify an id or data')));
}
};
@ -460,7 +463,7 @@ module.exports = function(registry) {
if (ctx.result !== null) return cb();
var fk = ctx.getArgByName('fk');
var msg = 'Unknown "' + toModelName + '" id "' + fk + '".';
var msg = g.f('Unknown "%s" id "%s".', toModelName, fk);
var error = new Error(msg);
error.statusCode = error.status = 404;
error.code = 'MODEL_NOT_FOUND';
@ -475,7 +478,7 @@ module.exports = function(registry) {
isStatic: false,
http: { verb: 'get', path: '/' + pathName },
accepts: { arg: 'refresh', type: 'boolean', http: { source: 'query' }},
description: 'Fetches hasOne relation ' + relationName + '.',
description: g.f('Fetches hasOne relation %s.', relationName),
accessType: 'READ',
returns: { arg: relationName, type: relation.modelTo.modelName, root: true },
rest: { after: convertNullToNotFoundError.bind(null, toModelName) },
@ -485,7 +488,7 @@ module.exports = function(registry) {
isStatic: false,
http: { verb: 'post', path: '/' + pathName },
accepts: { arg: 'data', type: toModelName, http: { source: 'body' }},
description: 'Creates a new instance in ' + relationName + ' of this model.',
description: g.f('Creates a new instance in %s of this model.', relationName),
accessType: 'WRITE',
returns: { arg: 'data', type: toModelName, root: true },
});
@ -494,7 +497,7 @@ module.exports = function(registry) {
isStatic: false,
http: { verb: 'put', path: '/' + pathName },
accepts: { arg: 'data', type: toModelName, http: { source: 'body' }},
description: 'Update ' + relationName + ' of this model.',
description: g.f('Update %s of this model.', relationName),
accessType: 'WRITE',
returns: { arg: 'data', type: toModelName, root: true },
});
@ -502,7 +505,7 @@ module.exports = function(registry) {
define('__destroy__' + relationName, {
isStatic: false,
http: { verb: 'delete', path: '/' + pathName },
description: 'Deletes ' + relationName + ' of this model.',
description: g.f('Deletes %s of this model.', relationName),
accessType: 'WRITE',
});
};
@ -516,9 +519,10 @@ module.exports = function(registry) {
isStatic: false,
http: { verb: 'get', path: '/' + pathName + '/:fk' },
accepts: { arg: 'fk', type: 'any',
description: 'Foreign key for ' + relationName, required: true,
description: g.f('Foreign key for %s', relationName),
required: true,
http: { source: 'path' }},
description: 'Find a related item by id for ' + relationName + '.',
description: g.f('Find a related item by id for %s.', relationName),
accessType: 'READ',
returns: { arg: 'result', type: toModelName, root: true },
rest: { after: convertNullToNotFoundError.bind(null, toModelName) },
@ -529,9 +533,10 @@ module.exports = function(registry) {
isStatic: false,
http: { verb: 'delete', path: '/' + pathName + '/:fk' },
accepts: { arg: 'fk', type: 'any',
description: 'Foreign key for ' + relationName, required: true,
description: g.f('Foreign key for %s', relationName),
required: true,
http: { source: 'path' }},
description: 'Delete a related item by id for ' + relationName + '.',
description: g.f('Delete a related item by id for %s.', relationName),
accessType: 'WRITE',
returns: [],
}, destroyByIdFunc);
@ -542,11 +547,12 @@ module.exports = function(registry) {
http: { verb: 'put', path: '/' + pathName + '/:fk' },
accepts: [
{ arg: 'fk', type: 'any',
description: 'Foreign key for ' + relationName, required: true,
description: g.f('Foreign key for %s', relationName),
required: true,
http: { source: 'path' }},
{ arg: 'data', type: toModelName, http: { source: 'body' }},
],
description: 'Update a related item by id for ' + relationName + '.',
description: g.f('Update a related item by id for %s.', relationName),
accessType: 'WRITE',
returns: { arg: 'result', type: toModelName, root: true },
}, updateByIdFunc);
@ -565,9 +571,10 @@ module.exports = function(registry) {
isStatic: false,
http: { verb: 'put', path: '/' + pathName + '/rel/:fk' },
accepts: [{ arg: 'fk', type: 'any',
description: 'Foreign key for ' + relationName, required: true,
description: g.f('Foreign key for %s', relationName),
required: true,
http: { source: 'path' }}].concat(accepts),
description: 'Add a related item by id for ' + relationName + '.',
description: g.f('Add a related item by id for %s.', relationName),
accessType: 'WRITE',
returns: { arg: relationName, type: modelThrough.modelName, root: true },
}, addFunc);
@ -577,9 +584,10 @@ module.exports = function(registry) {
isStatic: false,
http: { verb: 'delete', path: '/' + pathName + '/rel/:fk' },
accepts: { arg: 'fk', type: 'any',
description: 'Foreign key for ' + relationName, required: true,
description: g.f('Foreign key for %s', relationName),
required: true,
http: { source: 'path' }},
description: 'Remove the ' + relationName + ' relation to an item by id.',
description: g.f('Remove the %s relation to an item by id.', relationName),
accessType: 'WRITE',
returns: [],
}, removeFunc);
@ -591,9 +599,10 @@ module.exports = function(registry) {
isStatic: false,
http: { verb: 'head', path: '/' + pathName + '/rel/:fk' },
accepts: { arg: 'fk', type: 'any',
description: 'Foreign key for ' + relationName, required: true,
description: g.f('Foreign key for %s', relationName),
required: true,
http: { source: 'path' }},
description: 'Check the existence of ' + relationName + ' relation to an item by id.',
description: g.f('Check the existence of %s relation to an item by id.', relationName),
accessType: 'READ',
returns: { arg: 'exists', type: 'boolean', root: true },
rest: {
@ -602,7 +611,7 @@ module.exports = function(registry) {
if (ctx.result === false) {
var modelName = ctx.method.sharedClass.name;
var id = ctx.getArgByName('id');
var msg = 'Unknown "' + modelName + '" id "' + id + '".';
var msg = g.f('Unknown "%s" id "%s".', modelName, id);
var error = new Error(msg);
error.statusCode = error.status = 404;
error.code = 'MODEL_NOT_FOUND';
@ -636,7 +645,7 @@ module.exports = function(registry) {
isStatic: isStatic,
http: { verb: 'get', path: '/' + pathName },
accepts: { arg: 'filter', type: 'object' },
description: 'Queries ' + scopeName + ' of ' + this.modelName + '.',
description: g.f('Queries %s of %s.', scopeName, this.modelName),
accessType: 'READ',
returns: { arg: scopeName, type: [toModelName], root: true },
});
@ -645,7 +654,7 @@ module.exports = function(registry) {
isStatic: isStatic,
http: { verb: 'post', path: '/' + pathName },
accepts: { arg: 'data', type: toModelName, http: { source: 'body' }},
description: 'Creates a new instance in ' + scopeName + ' of this model.',
description: g.f('Creates a new instance in %s of this model.', scopeName),
accessType: 'WRITE',
returns: { arg: 'data', type: toModelName, root: true },
});
@ -653,7 +662,7 @@ module.exports = function(registry) {
define('__delete__' + scopeName, {
isStatic: isStatic,
http: { verb: 'delete', path: '/' + pathName },
description: 'Deletes all ' + scopeName + ' of this model.',
description: g.f('Deletes all %s of this model.', scopeName),
accessType: 'WRITE',
});
@ -661,7 +670,7 @@ module.exports = function(registry) {
isStatic: isStatic,
http: { verb: 'get', path: '/' + pathName + '/count' },
accepts: { arg: 'where', type: 'object', description: 'Criteria to match model instances' },
description: 'Counts ' + scopeName + ' of ' + this.modelName + '.',
description: g.f('Counts %s of %s.', scopeName, this.modelName),
accessType: 'READ',
returns: { arg: 'count', type: 'number' },
});
@ -708,7 +717,7 @@ module.exports = function(registry) {
acceptArgs = [
{
arg: paramName, type: 'any', http: { source: 'path' },
description: 'Foreign key for ' + relation.name + '.',
description: g.f('Foreign key for %s.', relation.name),
required: true,
},
];
@ -738,12 +747,12 @@ module.exports = function(registry) {
var getterFn = relation.modelFrom.prototype[getterName];
if (typeof getterFn !== 'function') {
throw new Error('Invalid remote method: `' + getterName + '`');
throw new Error(g.f('Invalid remote method: `%s`', getterName));
}
var nestedFn = relation.modelTo.prototype[method.name];
if (typeof nestedFn !== 'function') {
throw new Error('Invalid remote method: `' + method.name + '`');
throw new Error(g.f('Invalid remote method: `%s`', method.name));
}
var opts = {};
@ -835,8 +844,7 @@ module.exports = function(registry) {
});
});
} else {
var msg = 'Relation `' + relationName +
'` does not exist for model `' + this.modelName + '`';
var msg = g.f('Relation `%s` does not exist for model `%s`', relationName, this.modelName);
throw new Error(msg);
}
};

View File

@ -7,6 +7,7 @@
* Module Dependencies.
*/
var g = require('strong-globalize')();
var runtime = require('./runtime');
var assert = require('assert');
var async = require('async');
@ -65,9 +66,10 @@ module.exports = function(registry) {
function throwNotAttached(modelName, methodName) {
throw new Error(
'Cannot call ' + modelName + '.' + methodName + '().' +
' The ' + methodName + ' method has not been setup.' +
' The PersistedModel has not been correctly attached to a DataSource!'
g.f('Cannot call %s.%s().' +
' The %s method has not been setup.' +
' The {{PersistedModel}} has not been correctly attached to a {{DataSource}}!',
modelName, methodName, methodName)
);
}
@ -82,7 +84,7 @@ module.exports = function(registry) {
var modelName = ctx.method.sharedClass.name;
var id = ctx.getArgByName('id');
var msg = 'Unknown "' + modelName + '" id "' + id + '".';
var msg = g.f('Unknown "%s" id "%s".', modelName, id);
var error = new Error(msg);
error.statusCode = error.status = 404;
error.code = 'MODEL_NOT_FOUND';
@ -613,7 +615,7 @@ module.exports = function(registry) {
}
setRemoting(PersistedModel, 'create', {
description: 'Create a new instance of the model and persist it into the data source.',
description: g.f('Create a new instance of the model and persist it into the data source.'),
accessType: 'WRITE',
accepts: { arg: 'data', type: 'object', http: { source: 'body' }, description:
'Model instance data' },
@ -623,7 +625,8 @@ module.exports = function(registry) {
var upsertOptions = {
aliases: ['upsert', 'updateOrCreate'],
description: 'Patch an existing model instance or insert a new one into the data source.',
description: g.f('Patch an existing model instance or insert a new one ' +
'into the data source.'),
accessType: 'WRITE',
accepts: { arg: 'data', type: 'object', http: { source: 'body' }, description:
'Model instance data' },
@ -652,7 +655,7 @@ module.exports = function(registry) {
setRemoting(PersistedModel, 'replaceOrCreate', replaceOrCreateOptions);
setRemoting(PersistedModel, 'exists', {
description: 'Check whether a model instance exists in the data source.',
description: g.f('Check whether a model instance exists in the data source.'),
accessType: 'READ',
accepts: { arg: 'id', type: 'any', description: 'Model id', required: true },
returns: { arg: 'exists', type: 'boolean' },
@ -683,13 +686,13 @@ module.exports = function(registry) {
});
setRemoting(PersistedModel, 'findById', {
description: 'Find a model instance by id from the data source.',
description: g.f('Find a model instance by id from the data source.'),
accessType: 'READ',
accepts: [
{ arg: 'id', type: 'any', description: 'Model id', required: true,
http: { source: 'path' }},
{ arg: 'filter', type: 'object',
description: 'Filter defining fields and include' },
description: g.f('Filter defining fields and include') },
],
returns: { arg: 'data', type: typeName, root: true },
http: { verb: 'get', path: '/:id' },
@ -717,7 +720,7 @@ module.exports = function(registry) {
setRemoting(PersistedModel, 'find', {
description: 'Find all instances of the model matched by filter from the data source.',
description: g.f('Find all instances of the model matched by filter from the data source.'),
accessType: 'READ',
accepts: { arg: 'filter', type: 'object', description:
'Filter defining fields, where, include, order, offset, and limit' },
@ -726,7 +729,7 @@ module.exports = function(registry) {
});
setRemoting(PersistedModel, 'findOne', {
description: 'Find first instance of the model matched by filter from the data source.',
description: g.f('Find first instance of the model matched by filter from the data source.'),
accessType: 'READ',
accepts: { arg: 'filter', type: 'object', description:
'Filter defining fields, where, include, order, offset, and limit' },
@ -736,7 +739,7 @@ module.exports = function(registry) {
});
setRemoting(PersistedModel, 'destroyAll', {
description: 'Delete all matching records.',
description: g.f('Delete all matching records.'),
accessType: 'WRITE',
accepts: { arg: 'where', type: 'object', description: 'filter.where object' },
returns: {
@ -751,17 +754,17 @@ module.exports = function(registry) {
setRemoting(PersistedModel, 'updateAll', {
aliases: ['update'],
description: 'Update instances of the model matched by where from the data source.',
description: g.f('Update instances of the model matched by {{where}} from the data source.'),
accessType: 'WRITE',
accepts: [
{ arg: 'where', type: 'object', http: { source: 'query' },
description: 'Criteria to match model instances' },
{ arg: 'data', type: 'object', http: { source: 'body' },
description: 'An object of model property name/value pairs' },
description: g.f('An object of model property name/value pairs') },
],
returns: {
arg: 'count',
description: 'The number of instances updated',
description: g.f('The number of instances updated'),
type: 'object',
root: true,
},
@ -770,7 +773,7 @@ module.exports = function(registry) {
setRemoting(PersistedModel, 'deleteById', {
aliases: ['destroyById', 'removeById'],
description: 'Delete a model instance by id from the data source.',
description: g.f('Delete a model instance by id from the data source.'),
accessType: 'WRITE',
accepts: { arg: 'id', type: 'any', description: 'Model id', required: true,
http: { source: 'path' }},
@ -779,7 +782,7 @@ module.exports = function(registry) {
});
setRemoting(PersistedModel, 'count', {
description: 'Count instances of the model matched by where from the data source.',
description: g.f('Count instances of the model matched by where from the data source.'),
accessType: 'READ',
accepts: { arg: 'where', type: 'object', description: 'Criteria to match model instances' },
returns: { arg: 'count', type: 'number' },
@ -788,7 +791,8 @@ module.exports = function(registry) {
var updateAttributesOptions = {
aliases: ['updateAttributes'],
description: 'Patch attributes for a model instance and persist it into the data source.',
description: g.f('Patch attributes for a model instance and persist it into ' +
'the data source.'),
accessType: 'WRITE',
accepts: { arg: 'data', type: 'object', http: { source: 'body' }, description: 'An object of model property name/value pairs' },
returns: { arg: 'data', type: typeName, root: true },
@ -803,7 +807,7 @@ module.exports = function(registry) {
if (options.trackChanges || options.enableRemoteReplication) {
setRemoting(PersistedModel, 'diff', {
description: 'Get a set of deltas and conflicts since the given checkpoint.',
description: g.f('Get a set of deltas and conflicts since the given checkpoint.'),
accessType: 'READ',
accepts: [
{ arg: 'since', type: 'number', description: 'Find deltas since this checkpoint' },
@ -815,8 +819,8 @@ module.exports = function(registry) {
});
setRemoting(PersistedModel, 'changes', {
description: 'Get the changes to a model since a given checkpoint.' +
'Provide a filter object to reduce the number of results returned.',
description: g.f('Get the changes to a model since a given checkpoint.' +
'Provide a filter object to reduce the number of results returned.'),
accessType: 'READ',
accepts: [
{ arg: 'since', type: 'number', description:
@ -829,7 +833,7 @@ module.exports = function(registry) {
});
setRemoting(PersistedModel, 'checkpoint', {
description: 'Create a checkpoint.',
description: g.f('Create a checkpoint.'),
// The replication algorithm needs to create a source checkpoint,
// even though it is otherwise not making any source changes.
// We need to allow this method for users that don't have full
@ -840,14 +844,14 @@ module.exports = function(registry) {
});
setRemoting(PersistedModel, 'currentCheckpoint', {
description: 'Get the current checkpoint.',
description: g.f('Get the current checkpoint.'),
accessType: 'READ',
returns: { arg: 'checkpoint', type: 'object', root: true },
http: { verb: 'get', path: '/checkpoint' },
});
setRemoting(PersistedModel, 'createUpdates', {
description: 'Create an update list from a delta list.',
description: g.f('Create an update list from a delta list.'),
// This operation is read-only, it does not change any local data.
// It is called by the replication algorithm to compile a list
// of changes to apply on the target.
@ -858,14 +862,14 @@ module.exports = function(registry) {
});
setRemoting(PersistedModel, 'bulkUpdate', {
description: 'Run multiple updates at once. Note: this is not atomic.',
description: g.f('Run multiple updates at once. Note: this is not atomic.'),
accessType: 'WRITE',
accepts: { arg: 'updates', type: 'array' },
http: { verb: 'post', path: '/bulk-update' },
});
setRemoting(PersistedModel, 'findLastChange', {
description: 'Get the most recent change record for this instance.',
description: g.f('Get the most recent change record for this instance.'),
accessType: 'READ',
accepts: {
arg: 'id', type: 'any', required: true, http: { source: 'path' },
@ -877,8 +881,8 @@ module.exports = function(registry) {
setRemoting(PersistedModel, 'updateLastChange', {
description: [
'Update the properties of the most recent change record',
'kept for this instance.',
g.f('Update the properties of the most recent change record ' +
'kept for this instance.'),
],
accessType: 'WRITE',
accepts: [
@ -888,7 +892,7 @@ module.exports = function(registry) {
},
{
arg: 'data', type: 'object', http: { source: 'body' },
description: 'An object of Change property name/value pairs',
description: g.f('An object of Change property name/value pairs'),
},
],
returns: { arg: 'result', type: this.Change.modelName, root: true },
@ -897,7 +901,7 @@ module.exports = function(registry) {
}
setRemoting(PersistedModel, 'createChangeStream', {
description: 'Create a change stream.',
description: g.f('Create a change stream.'),
accessType: 'READ',
http: [
{ verb: 'post', path: '/change-stream' },
@ -1239,7 +1243,7 @@ module.exports = function(registry) {
if (err) return cb(err);
if (!inst) {
return cb &&
cb(new Error('Missing data for change: ' + change.modelId));
cb(new Error(g.f('Missing data for change: %s', change.modelId)));
}
if (inst.toObject) {
update.data = inst.toObject();
@ -1307,7 +1311,7 @@ module.exports = function(registry) {
async.parallel(tasks, function(err) {
if (err) return callback(err);
if (conflicts.length) {
err = new Error('Conflict');
err = new Error(g.f('Conflict'));
err.statusCode = 409;
err.details = { conflicts: conflicts };
return callback(err);
@ -1371,16 +1375,16 @@ module.exports = function(registry) {
case undefined:
case null:
return cb(new Error(
'Cannot apply bulk updates, ' +
g.f('Cannot apply bulk updates, ' +
'the connector does not correctly report ' +
'the number of updated records.'));
'the number of updated records.')));
default:
debug('%s.updateAll modified unexpected number of instances: %j',
Model.modelName, count);
return cb(new Error(
'Bulk update failed, the connector has modified unexpected ' +
'number of records: ' + JSON.stringify(count)));
g.f('Bulk update failed, the connector has modified unexpected ' +
'number of records: %s', JSON.stringify(count))));
}
});
}
@ -1453,16 +1457,16 @@ module.exports = function(registry) {
case undefined:
case null:
return cb(new Error(
'Cannot apply bulk updates, ' +
g.f('Cannot apply bulk updates, ' +
'the connector does not correctly report ' +
'the number of deleted records.'));
'the number of deleted records.')));
default:
debug('%s.deleteAll modified unexpected number of instances: %j',
Model.modelName, count);
return cb(new Error(
'Bulk update failed, the connector has deleted unexpected ' +
'number of records: ' + JSON.stringify(count)));
g.f('Bulk update failed, the connector has deleted unexpected ' +
'number of records: %s', JSON.stringify(count))));
}
});
}
@ -1676,8 +1680,8 @@ module.exports = function(registry) {
this.findLastChange(id, function(err, inst) {
if (err) return cb(err);
if (!inst) {
err = new Error('No change record found for ' +
self.modelName + ' with id ' + id);
err = new Error(g.f('No change record found for %s with id %s',
self.modelName, id));
err.statusCode = 404;
return cb(err);
}

View File

@ -3,6 +3,7 @@
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
var g = require('strong-globalize')();
var assert = require('assert');
var extend = require('util')._extend;
var juggler = require('loopback-datasource-juggler');
@ -111,8 +112,8 @@ Registry.prototype.createModel = function(name, properties, options) {
var baseName = BaseModel;
BaseModel = this.findModel(BaseModel);
if (!BaseModel) {
throw new Error('Model not found: model `' + name + '` is extending an unknown model `' +
baseName + '`.');
throw new Error(g.f('Model not found: model `%s` is extending an unknown model `%s`.',
name, baseName));
}
}
@ -185,7 +186,7 @@ Registry.prototype.configureModel = function(ModelCtor, config) {
relations[key] = extend(relations[key] || {}, config.relations[key]);
});
} else if (config.relations != null) {
console.warn('The relations property of `%s` configuration ' +
g.warn('The relations property of `%s` configuration ' +
'must be an object', modelName);
}
@ -196,7 +197,7 @@ Registry.prototype.configureModel = function(ModelCtor, config) {
addACL(acls, acl);
});
} else if (config.acls != null) {
console.warn('The acls property of `%s` configuration ' +
g.warn('The acls property of `%s` configuration ' +
'must be an array of objects', modelName);
}
@ -213,12 +214,12 @@ Registry.prototype.configureModel = function(ModelCtor, config) {
if (!(p in excludedProperties)) {
settings[p] = config.options[p];
} else {
console.warn('Property `%s` cannot be reconfigured for `%s`',
g.warn('Property `%s` cannot be reconfigured for `%s`',
p, modelName);
}
}
} else if (config.options != null) {
console.warn('The options property of `%s` configuration ' +
g.warn('The options property of `%s` configuration ' +
'must be an object', modelName);
}
@ -226,8 +227,8 @@ Registry.prototype.configureModel = function(ModelCtor, config) {
// configuration, so that the datasource picks up updated relations
if (config.dataSource) {
assert(config.dataSource instanceof DataSource,
'Cannot configure ' + ModelCtor.modelName +
': config.dataSource must be an instance of DataSource');
g.f('Cannot configure %s: {{config.dataSource}} must be an instance ' +
'of {{DataSource}}', ModelCtor.modelName));
ModelCtor.attachTo(config.dataSource);
debug('Attached model `%s` to dataSource `%s`',
modelName, config.dataSource.name);
@ -237,8 +238,8 @@ Registry.prototype.configureModel = function(ModelCtor, config) {
} else {
debug('Model `%s` is not attached to any DataSource, possibly by a mistake.',
modelName);
console.warn(
'The configuration of `%s` is missing `dataSource` property.\n' +
g.warn(
'The configuration of `%s` is missing {{`dataSource`}} property.\n' +
'Use `null` or `false` to mark models not attached to any data source.',
modelName);
}
@ -250,7 +251,7 @@ Registry.prototype.configureModel = function(ModelCtor, config) {
Registry.prototype._defineRemoteMethods = function(ModelCtor, methods) {
if (!methods) return;
if (typeof methods !== 'object') {
console.warn('Ignoring non-object "methods" setting of "%s".',
g.warn('Ignoring non-object "methods" setting of "%s".',
ModelCtor.modelName);
return;
}
@ -264,12 +265,12 @@ Registry.prototype._defineRemoteMethods = function(ModelCtor, methods) {
key = isStatic ? key : m[1];
meta.isStatic = isStatic;
} else if (meta.isStatic && m) {
throw new Error('Remoting metadata for ' + ModelCtor.modelName + '.' +
key + ' "isStatic" does not match new method name-based style.');
throw new Error(g.f('Remoting metadata for %s.%s {{"isStatic"}} does ' +
'not match new method name-based style.', ModelCtor.modelName, key));
} else {
key = isStatic ? key : m[1];
deprecated('Remoting metadata "isStatic" is deprecated. Please ' +
'specify "prototype.name" in method name instead for isStatic=false.');
deprecated(g.f('Remoting metadata {{"isStatic"}} is deprecated. Please ' +
'specify {{"prototype.name"}} in method name instead for {{isStatic=false}}.'));
}
ModelCtor.remoteMethod(key, meta);
});
@ -301,7 +302,7 @@ Registry.prototype.getModel = function(modelName) {
var model = this.findModel(modelName);
if (model) return model;
throw new Error('Model not found: ' + modelName);
throw new Error(g.f('Model not found: %s', modelName));
};
/**
@ -367,7 +368,7 @@ Registry.prototype.createDataSource = function(name, options) {
};
if (ds.settings && ds.settings.defaultForType) {
var msg = 'DataSource option "defaultForType" is no longer supported';
var msg = g.f('{{DataSource}} option {{"defaultForType"}} is no longer supported');
throw new Error(msg);
}

View File

@ -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 assert = require('assert');
var express = require('express');
var merge = require('util')._extend;
@ -188,7 +190,7 @@ proto.middleware = function(name, paths, handler) {
}
if (this._requestHandlingPhases.indexOf(name) === -1)
throw new Error('Unknown middleware phase ' + name);
throw new Error(g.f('Unknown {{middleware}} phase %s', name));
debug('use %s %s %s', fullPhaseName, paths, handlerName);

View File

@ -53,6 +53,7 @@
"nodemailer-stub-transport": "^1.0.0",
"serve-favicon": "^2.2.0",
"stable": "^0.1.5",
"strong-globalize": "^2.6.2",
"strong-remoting": "^3.0.0-alpha.1",
"uid2": "0.0.3",
"underscore.string": "^3.0.3"