diff --git a/test/api/v3/integration/payments/paypal/GET-payments_paypal_checkout_success.test.js b/test/api/v3/integration/payments/paypal/GET-payments_paypal_checkout_success.test.js index 233000372d..bae6423be0 100644 --- a/test/api/v3/integration/payments/paypal/GET-payments_paypal_checkout_success.test.js +++ b/test/api/v3/integration/payments/paypal/GET-payments_paypal_checkout_success.test.js @@ -1,8 +1,8 @@ import { generateUser, + translate as t, } from '../../../../../helpers/api-integration/v3'; import paypalPayments from '../../../../../../website/server/libs/payments/paypal'; -import apiMessages from '../../../../../../website/server/libs/apiMessages'; describe('payments : paypal #checkoutSuccess', () => { let endpoint = '/paypal/checkout/success'; @@ -17,7 +17,7 @@ describe('payments : paypal #checkoutSuccess', () => { .to.eventually.be.rejected.and.eql({ code: 400, error: 'BadRequest', - message: apiMessages('missingPaymentId'), + message: t('missingPaymentId'), }); }); @@ -26,7 +26,7 @@ describe('payments : paypal #checkoutSuccess', () => { .to.eventually.be.rejected.and.eql({ code: 400, error: 'BadRequest', - message: apiMessages('missingCustomerId'), + message: t('missingCustomerId'), }); }); diff --git a/test/api/v3/integration/payments/paypal/GET-payments_paypal_subscribe.test.js b/test/api/v3/integration/payments/paypal/GET-payments_paypal_subscribe.test.js index b6c6a765b7..3146eb0c5d 100644 --- a/test/api/v3/integration/payments/paypal/GET-payments_paypal_subscribe.test.js +++ b/test/api/v3/integration/payments/paypal/GET-payments_paypal_subscribe.test.js @@ -1,9 +1,9 @@ import { generateUser, + translate as t, } from '../../../../../helpers/api-integration/v3'; import paypalPayments from '../../../../../../website/server/libs/payments/paypal'; import shared from '../../../../../../website/common'; -import apiMessages from '../../../../../../website/server/libs/apiMessages'; describe('payments : paypal #subscribe', () => { let endpoint = '/paypal/subscribe'; @@ -17,7 +17,7 @@ describe('payments : paypal #subscribe', () => { await expect(user.get(endpoint)).to.eventually.be.rejected.and.eql({ code: 400, error: 'BadRequest', - message: apiMessages('missingSubKey'), + message: t('missingSubKey'), }); }); diff --git a/test/api/v3/integration/payments/paypal/GET-payments_paypal_subscribe_success.test.js b/test/api/v3/integration/payments/paypal/GET-payments_paypal_subscribe_success.test.js index f858851848..bace51302a 100644 --- a/test/api/v3/integration/payments/paypal/GET-payments_paypal_subscribe_success.test.js +++ b/test/api/v3/integration/payments/paypal/GET-payments_paypal_subscribe_success.test.js @@ -1,7 +1,7 @@ import { generateUser, + translate as t, } from '../../../../../helpers/api-integration/v3'; -import apiMessages from '../../../../../../website/server/libs/apiMessages'; import paypalPayments from '../../../../../../website/server/libs/payments/paypal'; describe('payments : paypal #subscribeSuccess', () => { @@ -16,7 +16,7 @@ describe('payments : paypal #subscribeSuccess', () => { await expect(user.get(endpoint)).to.eventually.be.rejected.and.eql({ code: 400, error: 'BadRequest', - message: apiMessages('missingPaypalBlock'), + message: t('missingPaypalBlock'), }); }); diff --git a/test/api/v3/integration/quests/POST-groups_groupId_quests_invite.test.js b/test/api/v3/integration/quests/POST-groups_groupId_quests_invite.test.js index ccda410914..7757c4c2ac 100644 --- a/test/api/v3/integration/quests/POST-groups_groupId_quests_invite.test.js +++ b/test/api/v3/integration/quests/POST-groups_groupId_quests_invite.test.js @@ -5,7 +5,6 @@ import { } from '../../../../helpers/api-v3-integration.helper'; import { v4 as generateUUID } from 'uuid'; import { quests as questScrolls } from '../../../../../website/common/script/content'; -import apiMessages from '../../../../../website/server/libs/apiMessages'; describe('POST /groups/:groupId/quests/invite/:questKey', () => { let questingGroup; @@ -69,7 +68,7 @@ describe('POST /groups/:groupId/quests/invite/:questKey', () => { await expect(leader.post(`/groups/${questingGroup._id}/quests/invite/${FAKE_QUEST}`)).to.eventually.be.rejected.and.eql({ code: 404, error: 'NotFound', - message: apiMessages('questNotFound', {key: FAKE_QUEST}), + message: t('questNotFound', {key: FAKE_QUEST}), }); }); diff --git a/test/api/v3/integration/user/POST-user_class_cast_spellId.test.js b/test/api/v3/integration/user/POST-user_class_cast_spellId.test.js index ba73fcd6d7..a141a31145 100644 --- a/test/api/v3/integration/user/POST-user_class_cast_spellId.test.js +++ b/test/api/v3/integration/user/POST-user_class_cast_spellId.test.js @@ -9,7 +9,6 @@ import { import { v4 as generateUUID } from 'uuid'; import { find } from 'lodash'; -import apiMessages from '../../../../../website/server/libs/apiMessages'; describe('POST /user/class/cast/:spellId', () => { let user; @@ -25,7 +24,7 @@ describe('POST /user/class/cast/:spellId', () => { .to.eventually.be.rejected.and.eql({ code: 404, error: 'NotFound', - message: apiMessages('spellNotFound', {spellId}), + message: t('spellNotFound', {spellId}), }); }); @@ -35,7 +34,7 @@ describe('POST /user/class/cast/:spellId', () => { .to.eventually.be.rejected.and.eql({ code: 404, error: 'NotFound', - message: apiMessages('spellNotFound', {spellId}), + message: t('spellNotFound', {spellId}), }); }); diff --git a/test/api/v3/integration/user/buy/POST-user_buy.test.js b/test/api/v3/integration/user/buy/POST-user_buy.test.js index 848f787618..37670d115b 100644 --- a/test/api/v3/integration/user/buy/POST-user_buy.test.js +++ b/test/api/v3/integration/user/buy/POST-user_buy.test.js @@ -5,7 +5,6 @@ import { translate as t, } from '../../../../../helpers/api-integration/v3'; import shared from '../../../../../../website/common/script'; -import apiMessages from '../../../../../../website/server/libs/apiMessages'; let content = shared.content; @@ -25,7 +24,7 @@ describe('POST /user/buy/:key', () => { .to.eventually.be.rejected.and.eql({ code: 404, error: 'NotFound', - message: apiMessages('itemNotFound', {key: 'notExisting'}), + message: t('itemNotFound', {key: 'notExisting'}), }); }); diff --git a/test/api/v3/integration/user/buy/POST-user_buy_gear.test.js b/test/api/v3/integration/user/buy/POST-user_buy_gear.test.js index 2af190f493..d3992ed1fe 100644 --- a/test/api/v3/integration/user/buy/POST-user_buy_gear.test.js +++ b/test/api/v3/integration/user/buy/POST-user_buy_gear.test.js @@ -2,8 +2,8 @@ import { generateUser, + translate as t, } from '../../../../../helpers/api-integration/v3'; -import apiMessages from '../../../../../../website/server/libs/apiMessages'; describe('POST /user/buy-gear/:key', () => { let user; @@ -21,7 +21,7 @@ describe('POST /user/buy-gear/:key', () => { .to.eventually.be.rejected.and.eql({ code: 404, error: 'NotFound', - message: apiMessages('itemNotFound', {key: 'notExisting'}), + message: t('itemNotFound', {key: 'notExisting'}), }); }); diff --git a/test/api/v3/integration/user/buy/POST-user_buy_quest.test.js b/test/api/v3/integration/user/buy/POST-user_buy_quest.test.js index 4224ff9cb1..f539a29a5a 100644 --- a/test/api/v3/integration/user/buy/POST-user_buy_quest.test.js +++ b/test/api/v3/integration/user/buy/POST-user_buy_quest.test.js @@ -3,7 +3,6 @@ import { translate as t, } from '../../../../../helpers/api-integration/v3'; import shared from '../../../../../../website/common/script'; -import apiMessages from '../../../../../../website/server/libs/apiMessages'; let content = shared.content; @@ -21,7 +20,7 @@ describe('POST /user/buy-quest/:key', () => { .to.eventually.be.rejected.and.eql({ code: 404, error: 'NotFound', - message: apiMessages('questNotFound', {key: 'notExisting'}), + message: t('questNotFound', {key: 'notExisting'}), }); }); diff --git a/test/api/v3/integration/user/buy/POST-user_buy_special_spell.test.js b/test/api/v3/integration/user/buy/POST-user_buy_special_spell.test.js index a132b57a59..f6c16febee 100644 --- a/test/api/v3/integration/user/buy/POST-user_buy_special_spell.test.js +++ b/test/api/v3/integration/user/buy/POST-user_buy_special_spell.test.js @@ -3,7 +3,6 @@ import { translate as t, } from '../../../../../helpers/api-integration/v3'; import shared from '../../../../../../website/common/script'; -import apiMessages from '../../../../../../website/server/libs/apiMessages'; let content = shared.content; @@ -21,7 +20,7 @@ describe('POST /user/buy-special-spell/:key', () => { .to.eventually.be.rejected.and.eql({ code: 404, error: 'NotFound', - message: apiMessages('spellNotFound', {spellId: 'notExisting'}), + message: t('spellNotFound', {spellId: 'notExisting'}), }); }); diff --git a/test/api/v3/integration/user/stats/POST-user_allocate.test.js b/test/api/v3/integration/user/stats/POST-user_allocate.test.js index fce5e10a6f..6487641c79 100644 --- a/test/api/v3/integration/user/stats/POST-user_allocate.test.js +++ b/test/api/v3/integration/user/stats/POST-user_allocate.test.js @@ -2,7 +2,6 @@ import { generateUser, translate as t, } from '../../../../../helpers/api-integration/v3'; -import apiMessages from '../../../../../../website/server/libs/apiMessages'; describe('POST /user/allocate', () => { let user; @@ -18,7 +17,7 @@ describe('POST /user/allocate', () => { .to.eventually.be.rejected.and.eql({ code: 400, error: 'BadRequest', - message: apiMessages('invalidAttribute', {attr: 'invalid'}), + message: t('invalidAttribute', {attr: 'invalid'}), }); }); diff --git a/test/api/v3/integration/webhook/POST-user_add_webhook.test.js b/test/api/v3/integration/webhook/POST-user_add_webhook.test.js index fdb95cf6a1..accb834dc4 100644 --- a/test/api/v3/integration/webhook/POST-user_add_webhook.test.js +++ b/test/api/v3/integration/webhook/POST-user_add_webhook.test.js @@ -3,7 +3,6 @@ import { translate as t, } from '../../../../helpers/api-integration/v3'; import { v4 as generateUUID } from 'uuid'; -import apiMessages from '../../../../../website/server/libs/apiMessages'; describe('POST /user/webhook', () => { let user, body; @@ -201,7 +200,7 @@ describe('POST /user/webhook', () => { await expect(user.post('/user/webhook', body)).to.eventually.be.rejected.and.eql({ code: 400, error: 'BadRequest', - message: apiMessages('groupIdRequired'), + message: t('groupIdRequired'), }); }); diff --git a/test/api/v3/integration/webhook/PUT-user_update_webhook.test.js b/test/api/v3/integration/webhook/PUT-user_update_webhook.test.js index 097dc3b174..994eff6750 100644 --- a/test/api/v3/integration/webhook/PUT-user_update_webhook.test.js +++ b/test/api/v3/integration/webhook/PUT-user_update_webhook.test.js @@ -3,7 +3,6 @@ import { translate as t, } from '../../../../helpers/api-integration/v3'; import { v4 as generateUUID} from 'uuid'; -import apiMessages from '../../../../../website/server/libs/apiMessages'; describe('PUT /user/webhook/:id', () => { let user, webhookToUpdate; @@ -127,7 +126,7 @@ describe('PUT /user/webhook/:id', () => { await expect(user.put(`/user/webhook/${webhookToUpdate.id}`, {type, options})).to.eventually.be.rejected.and.eql({ code: 400, error: 'BadRequest', - message: apiMessages('groupIdRequired'), + message: t('groupIdRequired'), }); }); }); diff --git a/test/api/v3/unit/models/webhook.test.js b/test/api/v3/unit/models/webhook.test.js index 9ca8e63c1e..ddb63e9caf 100644 --- a/test/api/v3/unit/models/webhook.test.js +++ b/test/api/v3/unit/models/webhook.test.js @@ -1,7 +1,6 @@ import { model as Webhook } from '../../../../../website/server/models/webhook'; import { BadRequest } from '../../../../../website/server/libs/errors'; import { v4 as generateUUID } from 'uuid'; -import apiMessages from '../../../../../website/server/libs/apiMessages'; describe('Webhook Model', () => { context('Instance Methods', () => { @@ -136,8 +135,8 @@ describe('Webhook Model', () => { wh.formatOptions(res); } catch (err) { expect(err).to.be.an.instanceOf(BadRequest); - - expect(err.message).to.eql(apiMessages('groupIdRequired')); + expect(res.t).to.be.calledOnce; + expect(res.t).to.be.calledWith('groupIdRequired'); done(); } }); diff --git a/test/common/ops/buy/buy.js b/test/common/ops/buy/buy.js index 15c41382cf..ab72d1f2b7 100644 --- a/test/common/ops/buy/buy.js +++ b/test/common/ops/buy/buy.js @@ -8,7 +8,6 @@ import { } from '../../../../website/common/script/libs/errors'; import i18n from '../../../../website/common/script/i18n'; import content from '../../../../website/common/script/content/index'; -import apiMessages from '../../../../website/server/libs/apiMessages'; describe('shared.ops.buy', () => { let user; @@ -41,7 +40,7 @@ describe('shared.ops.buy', () => { buy(user); } catch (err) { expect(err).to.be.an.instanceof(BadRequest); - expect(err.message).to.equal(apiMessages('missingKeyParam')); + expect(err.message).to.equal(i18n.t('missingKeyParam')); done(); } }); diff --git a/test/common/ops/buy/buyMarketGear.js b/test/common/ops/buy/buyMarketGear.js index 5170682c6e..48ce22ea1d 100644 --- a/test/common/ops/buy/buyMarketGear.js +++ b/test/common/ops/buy/buyMarketGear.js @@ -10,7 +10,6 @@ import { BadRequest, NotAuthorized, NotFound, } from '../../../../website/common/script/libs/errors'; import i18n from '../../../../website/common/script/i18n'; -import apiMessages from '../../../../website/server/libs/apiMessages'; function buyGear (user, req, analytics) { let buyOp = new BuyMarketGearOperation(user, req, analytics); @@ -191,7 +190,7 @@ describe('shared.ops.buyMarketGear', () => { buyGear(user); } catch (err) { expect(err).to.be.an.instanceof(BadRequest); - expect(err.message).to.equal(apiMessages('missingKeyParam')); + expect(err.message).to.equal(i18n.t('missingKeyParam')); done(); } }); @@ -203,7 +202,7 @@ describe('shared.ops.buyMarketGear', () => { buyGear(user, {params}); } catch (err) { expect(err).to.be.an.instanceof(NotFound); - expect(err.message).to.equal(apiMessages('itemNotFound', params)); + expect(err.message).to.equal(i18n.t('itemNotFound', params)); done(); } }); diff --git a/test/common/ops/buy/buyMysterySet.js b/test/common/ops/buy/buyMysterySet.js index ced59589da..5334d3e671 100644 --- a/test/common/ops/buy/buyMysterySet.js +++ b/test/common/ops/buy/buyMysterySet.js @@ -10,7 +10,6 @@ import { NotFound, } from '../../../../website/common/script/libs/errors'; import i18n from '../../../../website/common/script/i18n'; -import apiMessages from '../../../../website/server/libs/apiMessages'; describe('shared.ops.buyMysterySet', () => { let user; @@ -71,7 +70,7 @@ describe('shared.ops.buyMysterySet', () => { buyMysterySet(user); } catch (err) { expect(err).to.be.an.instanceof(BadRequest); - expect(err.message).to.equal(apiMessages('missingKeyParam')); + expect(err.message).to.equal(i18n.t('missingKeyParam')); done(); } }); diff --git a/test/common/ops/buy/buyQuest.js b/test/common/ops/buy/buyQuest.js index 6ab79c3546..390b65ee01 100644 --- a/test/common/ops/buy/buyQuest.js +++ b/test/common/ops/buy/buyQuest.js @@ -8,7 +8,6 @@ import { NotFound, } from '../../../../website/common/script/libs/errors'; import i18n from '../../../../website/common/script/i18n'; -import apiMessages from '../../../../website/server/libs/apiMessages'; describe('shared.ops.buyQuest', () => { let user; @@ -107,7 +106,7 @@ describe('shared.ops.buyQuest', () => { }); } catch (err) { expect(err).to.be.an.instanceof(NotFound); - expect(err.message).to.equal(apiMessages('questNotFound', {key: 'snarfblatter'})); + expect(err.message).to.equal(i18n.t('questNotFound', {key: 'snarfblatter'})); expect(user.items.quests).to.eql({}); expect(user.stats.gp).to.equal(9999); done(); @@ -152,7 +151,7 @@ describe('shared.ops.buyQuest', () => { buyQuest(user); } catch (err) { expect(err).to.be.an.instanceof(BadRequest); - expect(err.message).to.equal(apiMessages('missingKeyParam')); + expect(err.message).to.equal(i18n.t('missingKeyParam')); done(); } }); diff --git a/test/common/ops/buy/buySpecialSpell.js b/test/common/ops/buy/buySpecialSpell.js index 45ac2be1f2..97aade05ae 100644 --- a/test/common/ops/buy/buySpecialSpell.js +++ b/test/common/ops/buy/buySpecialSpell.js @@ -9,7 +9,6 @@ import { generateUser, } from '../../../helpers/common.helper'; import content from '../../../../website/common/script/content/index'; -import apiMessages from '../../../../website/server/libs/apiMessages'; describe('shared.ops.buySpecialSpell', () => { let user; @@ -29,7 +28,7 @@ describe('shared.ops.buySpecialSpell', () => { buySpecialSpell(user); } catch (err) { expect(err).to.be.an.instanceof(BadRequest); - expect(err.message).to.equal(apiMessages('missingKeyParam')); + expect(err.message).to.equal(i18n.t('missingKeyParam')); done(); } }); @@ -43,7 +42,7 @@ describe('shared.ops.buySpecialSpell', () => { }); } catch (err) { expect(err).to.be.an.instanceof(NotFound); - expect(err.message).to.equal(apiMessages('spellNotFound', {spellId: 'notExisting'})); + expect(err.message).to.equal(i18n.t('spellNotFound', {spellId: 'notExisting'})); done(); } }); diff --git a/test/common/ops/buy/hourglassPurchase.js b/test/common/ops/buy/hourglassPurchase.js index 2b768efddb..3684f7d416 100644 --- a/test/common/ops/buy/hourglassPurchase.js +++ b/test/common/ops/buy/hourglassPurchase.js @@ -8,7 +8,6 @@ import content from '../../../../website/common/script/content/index'; import { generateUser, } from '../../../helpers/common.helper'; -import apiMessages from '../../../../website/server/libs/apiMessages'; describe('common.ops.hourglassPurchase', () => { let user; @@ -29,7 +28,7 @@ describe('common.ops.hourglassPurchase', () => { hourglassPurchase(user, {params: {}}); } catch (err) { expect(err).to.be.an.instanceof(BadRequest); - expect(err.message).to.eql(apiMessages('missingKeyParam')); + expect(err.message).to.eql(i18n.t('missingKeyParam')); done(); } }); @@ -39,7 +38,7 @@ describe('common.ops.hourglassPurchase', () => { hourglassPurchase(user, {params: {key: 'Base'}}); } catch (err) { expect(err).to.be.an.instanceof(BadRequest); - expect(err.message).to.eql(apiMessages('missingTypeParam')); + expect(err.message).to.eql(i18n.t('missingTypeParam')); done(); } }); diff --git a/test/common/ops/feed.js b/test/common/ops/feed.js index 140464ede5..91c6a9cee9 100644 --- a/test/common/ops/feed.js +++ b/test/common/ops/feed.js @@ -9,7 +9,6 @@ import i18n from '../../../website/common/script/i18n'; import { generateUser, } from '../../helpers/common.helper'; -import apiMessages from '../../../website/server/libs/apiMessages'; describe('shared.ops.feed', () => { let user; @@ -24,7 +23,7 @@ describe('shared.ops.feed', () => { feed(user); } catch (err) { expect(err).to.be.an.instanceof(BadRequest); - expect(err.message).to.equal(apiMessages('missingPetFoodFeed')); + expect(err.message).to.equal(i18n.t('missingPetFoodFeed')); done(); } }); diff --git a/test/common/ops/hatch.js b/test/common/ops/hatch.js index 076966f4d3..fc6c7875f9 100644 --- a/test/common/ops/hatch.js +++ b/test/common/ops/hatch.js @@ -8,7 +8,6 @@ import i18n from '../../../website/common/script/i18n'; import { generateUser, } from '../../helpers/common.helper'; -import apiMessages from '../../../website/server/libs/apiMessages'; describe('shared.ops.hatch', () => { let user; @@ -25,7 +24,7 @@ describe('shared.ops.hatch', () => { hatch(user); } catch (err) { expect(err).to.be.an.instanceof(BadRequest); - expect(err.message).to.equal(apiMessages('missingEggHatchingPotion')); + expect(err.message).to.equal(i18n.t('missingEggHatchingPotionHatch')); expect(user.items.pets).to.be.empty; } }); diff --git a/test/common/ops/stats/allocate.js b/test/common/ops/stats/allocate.js index 2f3625acd6..1eaa14f88d 100644 --- a/test/common/ops/stats/allocate.js +++ b/test/common/ops/stats/allocate.js @@ -7,7 +7,6 @@ import i18n from '../../../../website/common/script/i18n'; import { generateUser, } from '../../../helpers/common.helper'; -import apiMessages from '../../../../website/server/libs/apiMessages'; describe('shared.ops.allocate', () => { let user; @@ -23,7 +22,7 @@ describe('shared.ops.allocate', () => { }); } catch (err) { expect(err).to.be.an.instanceof(BadRequest); - expect(err.message).to.equal(apiMessages('invalidAttribute', {attr: 'notValid'})); + expect(err.message).to.equal(i18n.t('invalidAttribute', {attr: 'notValid'})); done(); } }); diff --git a/test/common/ops/stats/allocateBulk.js b/test/common/ops/stats/allocateBulk.js index f505c6478a..e91de8cf9e 100644 --- a/test/common/ops/stats/allocateBulk.js +++ b/test/common/ops/stats/allocateBulk.js @@ -7,7 +7,6 @@ import i18n from '../../../../website/common/script/i18n'; import { generateUser, } from '../../../helpers/common.helper'; -import apiMessages from '../../../../website/server/libs/apiMessages'; describe('shared.ops.allocateBulk', () => { let user; @@ -28,7 +27,7 @@ describe('shared.ops.allocateBulk', () => { }); } catch (err) { expect(err).to.be.an.instanceof(BadRequest); - expect(err.message).to.equal(apiMessages('invalidAttribute', {attr: 'invalid'})); + expect(err.message).to.equal(i18n.t('invalidAttribute', {attr: 'invalid'})); done(); } }); @@ -38,7 +37,7 @@ describe('shared.ops.allocateBulk', () => { allocateBulk(user); } catch (err) { expect(err).to.be.an.instanceof(BadRequest); - expect(err.message).to.equal(apiMessages('statsObjectRequired')); + expect(err.message).to.equal(i18n.t('statsObjectRequired')); done(); } }); diff --git a/website/common/locales/en/character.json b/website/common/locales/en/character.json index 7bfe47d255..162fa6e701 100644 --- a/website/common/locales/en/character.json +++ b/website/common/locales/en/character.json @@ -201,6 +201,7 @@ "showQuickAllocation": "Show Stat Allocation", "hideQuickAllocation": "Hide Stat Allocation", "quickAllocationLevelPopover": "Each level earns you one Point to assign to a Stat of your choice. You can do so manually, or let the game decide for you using one of the Automatic Allocation options found in User Icon > Stats.", + "invalidAttribute": "\"<%= attr %>\" is not a valid Stat.", "notEnoughAttrPoints": "You don't have enough Stat Points.", "style": "Style", "facialhair": "Facial", @@ -223,5 +224,6 @@ "allocated": "Allocated", "buffs": "Buffs", "pointsAvailable": "Points Available", - "pts": "pts" + "pts": "pts", + "statsObjectRequired": "Stats update is required" } diff --git a/website/common/locales/en/contrib.json b/website/common/locales/en/contrib.json index 87b27f5d9a..4977277a27 100644 --- a/website/common/locales/en/contrib.json +++ b/website/common/locales/en/contrib.json @@ -49,6 +49,7 @@ "UUID": "User ID", "loadUser": "Load User", "noAdminAccess": "You don't have admin access.", + "pageMustBeNumber": "req.query.page must be a number", "userNotFound": "User not found.", "invalidUUID": "UUID must be valid", "title": "Title", diff --git a/website/common/locales/en/groups.json b/website/common/locales/en/groups.json index 495bb8c4a5..1b2ea93bd8 100644 --- a/website/common/locales/en/groups.json +++ b/website/common/locales/en/groups.json @@ -210,6 +210,7 @@ "partyOnName": "Party On", "partyUpText": "Joined a Party with another person! Have fun battling monsters and supporting each other.", "partyOnText": "Joined a Party with at least four people! Enjoy your increased accountability as you unite with your friends to vanquish your foes!", + "groupIdRequired": "\"groupId\" must be a valid UUID", "groupNotFound": "Group not found or you don't have access.", "groupTypesRequired": "You must supply a valid \"type\" query string.", "questLeaderCannotLeaveGroup": "You cannot leave your Party when you have started a quest. Abort the quest first.", @@ -219,6 +220,8 @@ "memberCannotRemoveYourself": "You cannot remove yourself!", "groupMemberNotFound": "User not found among group's members", "mustBeGroupMember": "Must be member of the group.", + "keepOrRemoveAll": "req.query.keep must be either \"keep-all\" or \"remove-all\"", + "keepOrRemove": "req.query.keep must be either \"keep\" or \"remove\"", "canOnlyInviteEmailUuid": "Can only invite using uuids or emails.", "inviteMissingEmail": "Missing email address in invite.", "inviteMissingUuid": "Missing user id in invite", @@ -325,6 +328,7 @@ "cantDeleteAssignedGroupTasks": "Can't delete group tasks that are assigned to you.", "confirmGuildPlanCreation": "Create this group?", "onlyGroupLeaderCanInviteToGroupPlan": "Only the group leader can invite users to a group with a subscription.", + "remainOrLeaveChallenges": "req.query.keep must be either 'remain-in-challenges' or 'leave-challenges'", "paymentDetails": "Payment Details", "aboutToJoinCancelledGroupPlan": "You are about to join a group with a canceled plan. You will NOT receive a free subscription.", "cannotChangeLeaderWithActiveGroupPlan": "You can not change the leader while the group has an active plan.", diff --git a/website/common/locales/en/npc.json b/website/common/locales/en/npc.json index 8e5651d04e..ee6ed35624 100644 --- a/website/common/locales/en/npc.json +++ b/website/common/locales/en/npc.json @@ -82,8 +82,14 @@ "ianBrokenText": "Welcome to the Quest Shop... Here you can use Quest Scrolls to battle monsters with your friends... Be sure to check out our fine array of Quest Scrolls for purchase on the right...", "featuredQuests": "Featured Quests!", + "missingKeyParam": "\"req.params.key\" is required.", + "itemNotFound": "Item \"<%= key %>\" not found.", "cannotBuyItem": "You can't buy this item.", + "missingTypeKeyEquip": "\"key\" and \"type\" are required parameters.", + "missingPetFoodFeed": "\"pet\" and \"food\" are required parameters.", "invalidPetName": "Invalid pet name supplied.", + "missingEggHatchingPotionHatch": "\"egg\" and \"hatchingPotion\" are required parameters.", + "invalidTypeEquip": "\"type\" must be one of 'equipped', 'pet', 'mount', 'costume'.", "mustPurchaseToSet": "Must purchase <%= val %> to set it on <%= key %>.", "typeRequired": "Type is required", "positiveAmountRequired": "Positive amount is required", diff --git a/website/common/locales/en/quests.json b/website/common/locales/en/quests.json index 5c09433384..0bfac41b6c 100644 --- a/website/common/locales/en/quests.json +++ b/website/common/locales/en/quests.json @@ -96,6 +96,7 @@ "questInvitationDoesNotExist": "No quest invitation has been sent out yet.", "questInviteNotFound": "No quest invitation found.", "guildQuestsNotSupported": "Guilds cannot be invited on quests.", + "questNotFound": "Quest \"<%= key %>\" not found.", "questNotOwned": "You don't own that quest scroll.", "questNotGoldPurchasable": "Quest \"<%= key %>\" is not a Gold-purchasable quest.", "questLevelTooHigh": "You must be level <%= level %> to begin this quest.", diff --git a/website/common/locales/en/spells.json b/website/common/locales/en/spells.json index d67816a19a..773e3301ba 100644 --- a/website/common/locales/en/spells.json +++ b/website/common/locales/en/spells.json @@ -72,6 +72,7 @@ "spellSpecialSandText": "Sand", "spellSpecialSandNotes": "Reverse the spell that made you a sea star.", + "spellNotFound": "Skill \"<%= spellId %>\" not found.", "partyNotFound": "Party not found", "targetIdUUID": "\"targetId\" must be a valid User ID.", "challengeTasksNoCast": "Casting a skill on challenge tasks is not allowed.", diff --git a/website/common/locales/en/subscriber.json b/website/common/locales/en/subscriber.json index 6095d37471..948f4c9852 100644 --- a/website/common/locales/en/subscriber.json +++ b/website/common/locales/en/subscriber.json @@ -176,6 +176,12 @@ "invalidCoupon": "Invalid coupon code.", "couponUsed": "Coupon code already used.", "couponCodeRequired": "The coupon code is required.", + "eventRequired": "\"req.params.event\" is required.", + "countRequired": "\"req.query.count\" is required.", + "missingPaymentId": "Missing req.query.paymentId", + "missingCustomerId": "Missing req.query.customerId", + "missingPaypalBlock": "Missing req.session.paypalBlock", + "missingSubKey": "Missing req.query.sub", "paypalCanceled": "Your subscription has been canceled", "earnGemsMonthly": "Earn up to **<%= cap %> Gems** per month", "receiveMysticHourglass": "Receive a Mystic Hourglass!", diff --git a/website/common/locales/en/tasks.json b/website/common/locales/en/tasks.json index afaba0032a..9990119356 100644 --- a/website/common/locales/en/tasks.json +++ b/website/common/locales/en/tasks.json @@ -145,6 +145,7 @@ "rewardHelp3": "Special equipment will appear here during World Events.", "rewardHelp4": "Don't be afraid to set custom Rewards! Check out some samples here.", "clickForHelp": "Click for help", + "taskIdRequired": "\"taskId\" must be a valid UUID.", "taskAliasAlreadyUsed": "Task alias already used on another task.", "taskNotFound": "Task not found.", "invalidTaskType": "Task type must be one of \"habit\", \"daily\", \"todo\", \"reward\".", diff --git a/website/common/script/ops/buy/buy.js b/website/common/script/ops/buy/buy.js index 938fa443af..b8f56aab7b 100644 --- a/website/common/script/ops/buy/buy.js +++ b/website/common/script/ops/buy/buy.js @@ -1,3 +1,4 @@ +import i18n from '../../i18n'; import get from 'lodash/get'; import { BadRequest, @@ -10,7 +11,6 @@ import {BuyQuestWithGoldOperation} from './buyQuest'; import buySpecialSpell from './buySpecialSpell'; import purchaseOp from './purchase'; import hourglassPurchase from './hourglassPurchase'; -import apiMessages from '../../../../server/libs/apiMessages'; // @TODO: remove the req option style. Dependency on express structure is an anti-pattern // We should either have more parms or a set structure validated by a Type checker @@ -19,7 +19,7 @@ import apiMessages from '../../../../server/libs/apiMessages'; module.exports = function buy (user, req = {}, analytics) { let key = get(req, 'params.key'); - if (!key) throw new BadRequest(apiMessages('missingKeyParam')); + if (!key) throw new BadRequest(i18n.t('missingKeyParam', req.language)); // @TODO: Slowly remove the need for key and use type instead // This should evenutally be the 'factory' function with vendor classes diff --git a/website/common/script/ops/buy/buyMarketGear.js b/website/common/script/ops/buy/buyMarketGear.js index 478369bce0..06fe881e48 100644 --- a/website/common/script/ops/buy/buyMarketGear.js +++ b/website/common/script/ops/buy/buyMarketGear.js @@ -13,7 +13,6 @@ import ultimateGear from '../../fns/ultimateGear'; import {removePinnedGearAddPossibleNewOnes} from '../pinnedGearUtils'; import { AbstractGoldItemOperation } from './abstractBuyOperation'; -import apiMessages from '../../../../server/libs/apiMessages'; export class BuyMarketGearOperation extends AbstractGoldItemOperation { constructor (user, req, analytics) { @@ -26,10 +25,9 @@ export class BuyMarketGearOperation extends AbstractGoldItemOperation { extractAndValidateParams (user, req) { let key = this.key = get(req, 'params.key'); - if (!key) throw new BadRequest(apiMessages('missingKeyParam')); - + if (!key) throw new BadRequest(this.i18n('missingKeyParam')); let item = content.gear.flat[key]; - if (!item) throw new NotFound(apiMessages('itemNotFound', {key})); + if (!item) throw new NotFound(this.i18n('itemNotFound', {key})); this.canUserPurchase(user, item); diff --git a/website/common/script/ops/buy/buyMysterySet.js b/website/common/script/ops/buy/buyMysterySet.js index 4ba3a53185..3a8b17a011 100644 --- a/website/common/script/ops/buy/buyMysterySet.js +++ b/website/common/script/ops/buy/buyMysterySet.js @@ -7,11 +7,10 @@ import { NotAuthorized, NotFound, } from '../../libs/errors'; -import apiMessages from '../../../../server/libs/apiMessages'; module.exports = function buyMysterySet (user, req = {}, analytics) { let key = get(req, 'params.key'); - if (!key) throw new BadRequest(apiMessages('missingKeyParam')); + if (!key) throw new BadRequest(i18n.t('missingKeyParam', req.language)); if (!(user.purchased.plan.consecutive.trinkets > 0)) { throw new NotAuthorized(i18n.t('notEnoughHourglasses', req.language)); diff --git a/website/common/script/ops/buy/buyQuest.js b/website/common/script/ops/buy/buyQuest.js index a9cd2ff80c..e30513347b 100644 --- a/website/common/script/ops/buy/buyQuest.js +++ b/website/common/script/ops/buy/buyQuest.js @@ -5,7 +5,6 @@ import { } from '../../libs/errors'; import content from '../../content/index'; import get from 'lodash/get'; -import apiMessages from '../../../../server/libs/apiMessages'; import {AbstractGoldItemOperation} from './abstractBuyOperation'; @@ -31,7 +30,7 @@ export class BuyQuestWithGoldOperation extends AbstractGoldItemOperation { extractAndValidateParams (user, req) { let key = this.key = get(req, 'params.key'); - if (!key) throw new BadRequest(apiMessages('missingKeyParam')); + if (!key) throw new BadRequest(this.i18n('missingKeyParam')); if (key === 'lostMasterclasser1' && !this.userAbleToStartMasterClasser(user)) { throw new NotAuthorized(this.i18n('questUnlockLostMasterclasser')); @@ -39,7 +38,7 @@ export class BuyQuestWithGoldOperation extends AbstractGoldItemOperation { let item = content.quests[key]; - if (!item) throw new NotFound(apiMessages('questNotFound', {key})); + if (!item) throw new NotFound(this.i18n('questNotFound', {key})); if (!(item.category === 'gold' && item.goldValue)) { throw new NotAuthorized(this.i18n('questNotGoldPurchasable', {key})); diff --git a/website/common/script/ops/buy/buySpecialSpell.js b/website/common/script/ops/buy/buySpecialSpell.js index 09d012d28a..d6a8492c81 100644 --- a/website/common/script/ops/buy/buySpecialSpell.js +++ b/website/common/script/ops/buy/buySpecialSpell.js @@ -8,16 +8,15 @@ import { NotAuthorized, NotFound, } from '../../libs/errors'; -import apiMessages from '../../../../server/libs/apiMessages'; module.exports = function buySpecialSpell (user, req = {}, analytics) { let key = get(req, 'params.key'); let quantity = req.quantity || 1; - if (!key) throw new BadRequest(apiMessages('missingKeyParam')); + if (!key) throw new BadRequest(i18n.t('missingKeyParam', req.language)); let item = content.special[key]; - if (!item) throw new NotFound(apiMessages('spellNotFound', {spellId: key})); + if (!item) throw new NotFound(i18n.t('spellNotFound', {spellId: key}, req.language)); if (user.stats.gp < item.value * quantity) { throw new NotAuthorized(i18n.t('messageNotEnoughGold', req.language)); diff --git a/website/common/script/ops/buy/hourglassPurchase.js b/website/common/script/ops/buy/hourglassPurchase.js index 4e80068d18..d9afc4b440 100644 --- a/website/common/script/ops/buy/hourglassPurchase.js +++ b/website/common/script/ops/buy/hourglassPurchase.js @@ -7,14 +7,13 @@ import { BadRequest, NotAuthorized, } from '../../libs/errors'; -import apiMessages from '../../../../server/libs/apiMessages'; module.exports = function purchaseHourglass (user, req = {}, analytics) { let key = get(req, 'params.key'); - if (!key) throw new BadRequest(apiMessages('missingKeyParam')); + if (!key) throw new BadRequest(i18n.t('missingKeyParam', req.language)); let type = get(req, 'params.type'); - if (!type) throw new BadRequest(apiMessages('missingTypeParam')); + if (!type) throw new BadRequest(i18n.t('missingTypeParam', req.language)); if (!content.timeTravelStable[type]) { throw new NotAuthorized(i18n.t('typeNotAllowedHourglass', {allowedTypes: keys(content.timeTravelStable).toString()}, req.language)); diff --git a/website/common/script/ops/equip.js b/website/common/script/ops/equip.js index dca83d2f9c..02f13e935c 100644 --- a/website/common/script/ops/equip.js +++ b/website/common/script/ops/equip.js @@ -6,7 +6,6 @@ import { BadRequest, } from '../libs/errors'; import get from 'lodash/get'; -import apiMessages from '../../../server/libs/apiMessages'; module.exports = function equip (user, req = {}) { // Being type a parameter followed by another parameter @@ -14,9 +13,9 @@ module.exports = function equip (user, req = {}) { let type = get(req, 'params.type', 'equipped'); let key = get(req, 'params.key'); - if (!key || !type) throw new BadRequest(apiMessages('missingTypeKeyEquip')); + if (!key || !type) throw new BadRequest(i18n.t('missingTypeKeyEquip', req.language)); if (['mount', 'pet', 'costume', 'equipped'].indexOf(type) === -1) { - throw new BadRequest(apiMessages('invalidTypeEquip')); + throw new BadRequest(i18n.t('invalidTypeEquip', req.language)); } let message; diff --git a/website/common/script/ops/feed.js b/website/common/script/ops/feed.js index 5d49e0e67e..cbe0e347f9 100644 --- a/website/common/script/ops/feed.js +++ b/website/common/script/ops/feed.js @@ -6,7 +6,6 @@ import { NotAuthorized, NotFound, } from '../libs/errors'; -import apiMessages from '../../../server/libs/apiMessages'; function evolve (user, pet, req) { user.items.pets[pet.key] = -1; @@ -25,7 +24,7 @@ module.exports = function feed (user, req = {}) { let pet = get(req, 'params.pet'); let foodK = get(req, 'params.food'); - if (!pet || !foodK) throw new BadRequest(apiMessages('missingPetFoodFeed')); + if (!pet || !foodK) throw new BadRequest(i18n.t('missingPetFoodFeed', req.language)); pet = content.petInfo[pet]; diff --git a/website/common/script/ops/hatch.js b/website/common/script/ops/hatch.js index 1efc41991e..15129e03f0 100644 --- a/website/common/script/ops/hatch.js +++ b/website/common/script/ops/hatch.js @@ -6,14 +6,13 @@ import { NotAuthorized, NotFound, } from '../libs/errors'; -import apiMessages from '../../../server/libs/apiMessages'; module.exports = function hatch (user, req = {}) { let egg = get(req, 'params.egg'); let hatchingPotion = get(req, 'params.hatchingPotion'); if (!(egg && hatchingPotion)) { - throw new BadRequest(apiMessages('missingEggHatchingPotion')); + throw new BadRequest(i18n.t('missingEggHatchingPotionHatch', req.language)); } if (!(user.items.eggs[egg] > 0 && user.items.hatchingPotions[hatchingPotion] > 0)) { diff --git a/website/common/script/ops/stats/allocate.js b/website/common/script/ops/stats/allocate.js index 707c34fcf1..70b5944c92 100644 --- a/website/common/script/ops/stats/allocate.js +++ b/website/common/script/ops/stats/allocate.js @@ -7,13 +7,12 @@ import { NotAuthorized, } from '../../libs/errors'; import i18n from '../../i18n'; -import apiMessages from '../../../../server/libs/apiMessages'; module.exports = function allocate (user, req = {}) { let stat = get(req, 'query.stat', 'str'); if (ATTRIBUTES.indexOf(stat) === -1) { - throw new BadRequest(apiMessages('invalidAttribute', {attr: stat})); + throw new BadRequest(i18n.t('invalidAttribute', {attr: stat}, req.language)); } if (user.stats.points > 0) { diff --git a/website/common/script/ops/stats/allocateBulk.js b/website/common/script/ops/stats/allocateBulk.js index d38b25c012..f44800a813 100644 --- a/website/common/script/ops/stats/allocateBulk.js +++ b/website/common/script/ops/stats/allocateBulk.js @@ -7,18 +7,17 @@ import { NotAuthorized, } from '../../libs/errors'; import i18n from '../../i18n'; -import apiMessages from '../../../../server/libs/apiMessages'; module.exports = function allocateBulk (user, req = {}) { const stats = get(req, 'body.stats'); - if (!stats) throw new BadRequest(apiMessages('statsObjectRequired')); + if (!stats) throw new BadRequest(i18n.t('statsObjectRequired', req.language)); const statKeys = Object.keys(stats); const invalidStats = statKeys.filter(statKey => { return ATTRIBUTES.indexOf(statKey) === -1; }); if (invalidStats.length > 0) { - throw new BadRequest(apiMessages('invalidAttribute', {attr: invalidStats.join(',')})); + throw new BadRequest(i18n.t('invalidAttribute', {attr: invalidStats.join(',')}, req.language)); } if (user.stats.points <= 0) { diff --git a/website/server/controllers/api-v3/challenges.js b/website/server/controllers/api-v3/challenges.js index 2e23cb2524..27b721f583 100644 --- a/website/server/controllers/api-v3/challenges.js +++ b/website/server/controllers/api-v3/challenges.js @@ -27,7 +27,6 @@ import { createChallenge, cleanUpTask, } from '../../libs/challenges'; -import apiMessages from '../../libs/apiMessages'; let api = {}; @@ -188,7 +187,7 @@ api.createChallenge = { async handler (req, res) { let user = res.locals.user; - req.checkBody('group', apiMessages('groupIdRequired')).notEmpty(); + req.checkBody('group', res.t('groupIdRequired')).notEmpty(); const validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; @@ -445,7 +444,7 @@ api.getGroupChallenges = { let user = res.locals.user; let groupId = req.params.groupId; - req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); + req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; diff --git a/website/server/controllers/api-v3/chat.js b/website/server/controllers/api-v3/chat.js index 1c0a495fde..df622ced54 100644 --- a/website/server/controllers/api-v3/chat.js +++ b/website/server/controllers/api-v3/chat.js @@ -18,7 +18,6 @@ import bannedWords from '../../libs/bannedWords'; import guildsAllowingBannedWords from '../../libs/guildsAllowingBannedWords'; import { getMatchesByWordArray } from '../../libs/stringUtils'; import bannedSlurs from '../../libs/bannedSlurs'; -import apiMessages from '../../libs/apiMessages'; const FLAG_REPORT_EMAILS = nconf.get('FLAG_REPORT_EMAIL').split(',').map((email) => { return { email, canSend: true }; @@ -66,7 +65,7 @@ api.getChat = { async handler (req, res) { let user = res.locals.user; - req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); + req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; @@ -105,7 +104,7 @@ api.postChat = { let groupId = req.params.groupId; let chatUpdated; - req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); + req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); req.sanitize('message').trim(); req.checkBody('message', res.t('messageGroupChatBlankMessage')).notEmpty(); @@ -225,7 +224,7 @@ api.likeChat = { let user = res.locals.user; let groupId = req.params.groupId; - req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); + req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); req.checkParams('chatId', res.t('chatIdRequired')).notEmpty(); let validationErrors = req.validationErrors(); @@ -318,7 +317,7 @@ api.clearChatFlags = { let groupId = req.params.groupId; let chatId = req.params.chatId; - req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); + req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); req.checkParams('chatId', res.t('chatIdRequired')).notEmpty(); let validationErrors = req.validationErrors(); @@ -391,7 +390,7 @@ api.seenChat = { let user = res.locals.user; let groupId = req.params.groupId; - req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); + req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; @@ -458,7 +457,7 @@ api.deleteChat = { let groupId = req.params.groupId; let chatId = req.params.chatId; - req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); + req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); req.checkParams('chatId', res.t('chatIdRequired')).notEmpty(); let validationErrors = req.validationErrors(); diff --git a/website/server/controllers/api-v3/coupon.js b/website/server/controllers/api-v3/coupon.js index 02681698d6..5fc0f4cbf1 100644 --- a/website/server/controllers/api-v3/coupon.js +++ b/website/server/controllers/api-v3/coupon.js @@ -7,7 +7,6 @@ import { ensureSudo } from '../../middlewares/ensureAccessRight'; import { model as Coupon } from '../../models/coupon'; import _ from 'lodash'; import couponCode from 'coupon-code'; -import apiMessages from '../../libs/apiMessages'; let api = {}; @@ -70,8 +69,8 @@ api.generateCoupons = { url: '/coupons/generate/:event', middlewares: [authWithHeaders(), ensureSudo], async handler (req, res) { - req.checkParams('event', apiMessages('eventRequired')).notEmpty(); - req.checkQuery('count', apiMessages('countRequired')).notEmpty().isNumeric(); + req.checkParams('event', res.t('eventRequired')).notEmpty(); + req.checkQuery('count', res.t('countRequired')).notEmpty().isNumeric(); let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; diff --git a/website/server/controllers/api-v3/groups.js b/website/server/controllers/api-v3/groups.js index 9fd2bfb949..f1264ca17c 100644 --- a/website/server/controllers/api-v3/groups.js +++ b/website/server/controllers/api-v3/groups.js @@ -275,7 +275,7 @@ api.createGroupPlan = { * * @apiError (400) {BadRequest} groupTypesRequired Group types are required * @apiError (400) {BadRequest} guildsPaginateBooleanString Paginate query parameter must be a boolean (true or false) - * @apiError (400) {BadRequest} queryPageInteger Page query parameter must be a positive integer + * @apiError (400) {BadRequest} guildsPageInteger Page query parameter must be a positive integer * @apiError (400) {BadRequest} guildsOnlyPaginate Only public guilds support pagination * * @apiSuccess {Object[]} data An array of the requested groups (See /website/server/models/group.js) @@ -296,7 +296,7 @@ api.getGroups = { req.checkQuery('type', res.t('groupTypesRequired')).notEmpty(); // pagination options, can only be used with public guilds req.checkQuery('paginate').optional().isIn(['true', 'false'], apiMessages('guildsPaginateBooleanString')); - req.checkQuery('page').optional().isInt({min: 0}, apiMessages('queryPageInteger')); + req.checkQuery('page').optional().isInt({min: 0}, apiMessages('guildsPageInteger')); let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; @@ -381,7 +381,7 @@ api.getGroup = { async handler (req, res) { let user = res.locals.user; - req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); + req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; @@ -439,7 +439,7 @@ api.updateGroup = { async handler (req, res) { let user = res.locals.user; - req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); + req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; @@ -503,7 +503,7 @@ api.joinGroup = { let user = res.locals.user; let inviter; - req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); // .isUUID(); can't be used because it would block 'habitrpg' or 'party' + req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); // .isUUID(); can't be used because it would block 'habitrpg' or 'party' let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; @@ -673,7 +673,7 @@ api.rejectGroupInvite = { async handler (req, res) { let user = res.locals.user; - req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); // .isUUID(); can't be used because it would block 'habitrpg' or 'party' + req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); // .isUUID(); can't be used because it would block 'habitrpg' or 'party' let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; @@ -747,10 +747,10 @@ api.leaveGroup = { middlewares: [authWithHeaders()], async handler (req, res) { let user = res.locals.user; - req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); + req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); // When removing the user from challenges, should we keep the tasks? - req.checkQuery('keep', apiMessages('keepOrRemoveAll')).optional().isIn(['keep-all', 'remove-all']); - req.checkBody('keepChallenges', apiMessages('groupRemainOrLeaveChallenges')).optional().isIn(['remain-in-challenges', 'leave-challenges']); + req.checkQuery('keep', res.t('keepOrRemoveAll')).optional().isIn(['keep-all', 'remove-all']); + req.checkBody('keepChallenges', res.t('remainOrLeaveChallenges')).optional().isIn(['remain-in-challenges', 'leave-challenges']); let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; @@ -835,7 +835,7 @@ api.removeGroupMember = { async handler (req, res) { let user = res.locals.user; - req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); + req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); req.checkParams('memberId', res.t('userIdRequired')).notEmpty().isUUID(); let validationErrors = req.validationErrors(); @@ -1155,7 +1155,7 @@ api.inviteToGroup = { if (user.flags.chatRevoked) throw new NotAuthorized(res.t('cannotInviteWhenMuted')); - req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); + req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); if (user.invitesSent >= MAX_EMAIL_INVITES_BY_USER) throw new NotAuthorized(res.t('inviteLimitReached', { techAssistanceEmail: TECH_ASSISTANCE_EMAIL })); diff --git a/website/server/controllers/api-v3/hall.js b/website/server/controllers/api-v3/hall.js index adfccf7dc9..5d836407b3 100644 --- a/website/server/controllers/api-v3/hall.js +++ b/website/server/controllers/api-v3/hall.js @@ -5,7 +5,6 @@ import { NotFound, } from '../../libs/errors'; import _ from 'lodash'; -import apiMessages from '../../libs/apiMessages'; let api = {}; @@ -63,7 +62,7 @@ api.getPatrons = { url: '/hall/patrons', middlewares: [authWithHeaders()], async handler (req, res) { - req.checkQuery('page').optional().isInt({min: 0}, apiMessages('queryPageInteger')); + req.checkQuery('page', res.t('pageMustBeNumber')).optional().isNumeric(); let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; diff --git a/website/server/controllers/api-v3/quests.js b/website/server/controllers/api-v3/quests.js index d9c39b37cd..7ae92b1b3a 100644 --- a/website/server/controllers/api-v3/quests.js +++ b/website/server/controllers/api-v3/quests.js @@ -17,7 +17,6 @@ import { } from '../../libs/email'; import common from '../../../common'; import { sendNotification as sendPushNotification } from '../../libs/pushNotifications'; -import apiMessages from '../../libs/apiMessages'; const questScrolls = common.content.quests; @@ -61,7 +60,7 @@ api.inviteToQuest = { let questKey = req.params.questKey; let quest = questScrolls[questKey]; - req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); + req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; @@ -70,7 +69,7 @@ api.inviteToQuest = { if (!group) throw new NotFound(res.t('groupNotFound')); if (group.type !== 'party') throw new NotAuthorized(res.t('guildQuestsNotSupported')); - if (!quest) throw new NotFound(apiMessages('questNotFound', { key: questKey })); + if (!quest) throw new NotFound(res.t('questNotFound', { key: questKey })); if (!user.items.quests[questKey]) throw new NotAuthorized(res.t('questNotOwned')); if (user.stats.lvl < quest.lvl) throw new NotAuthorized(res.t('questLevelTooHigh', { level: quest.lvl })); if (group.quest.key) throw new NotAuthorized(res.t('questAlreadyUnderway')); @@ -173,7 +172,7 @@ api.acceptQuest = { async handler (req, res) { let user = res.locals.user; - req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); + req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; @@ -232,7 +231,7 @@ api.rejectQuest = { async handler (req, res) { let user = res.locals.user; - req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); + req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; @@ -295,7 +294,7 @@ api.forceStart = { async handler (req, res) { let user = res.locals.user; - req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); + req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; @@ -357,7 +356,7 @@ api.cancelQuest = { let user = res.locals.user; let groupId = req.params.groupId; - req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); + req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; @@ -409,7 +408,7 @@ api.abortQuest = { let user = res.locals.user; let groupId = req.params.groupId; - req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); + req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; @@ -467,7 +466,7 @@ api.leaveQuest = { let user = res.locals.user; let groupId = req.params.groupId; - req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); + req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; diff --git a/website/server/controllers/api-v3/tasks.js b/website/server/controllers/api-v3/tasks.js index 97d79cb3f6..be8ded5164 100644 --- a/website/server/controllers/api-v3/tasks.js +++ b/website/server/controllers/api-v3/tasks.js @@ -23,7 +23,6 @@ import common from '../../../common'; import _ from 'lodash'; import logger from '../../libs/logger'; import moment from 'moment'; -import apiMessages from '../../libs/apiMessages'; const MAX_SCORE_NOTES_LENGTH = 256; @@ -430,7 +429,7 @@ api.updateTask = { let user = res.locals.user; let challenge; - req.checkParams('taskId', apiMessages('taskIdRequired')).notEmpty(); + req.checkParams('taskId', res.t('taskIdRequired')).notEmpty(); let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; @@ -710,7 +709,7 @@ api.moveTask = { url: '/tasks/:taskId/move/to/:position', middlewares: [authWithHeaders()], async handler (req, res) { - req.checkParams('taskId', apiMessages('taskIdRequired')).notEmpty(); + req.checkParams('taskId', res.t('taskIdRequired')).notEmpty(); req.checkParams('position', res.t('positionRequired')).notEmpty().isNumeric(); let validationErrors = req.validationErrors(); @@ -783,7 +782,7 @@ api.addChecklistItem = { let challenge; let group; - req.checkParams('taskId', apiMessages('taskIdRequired')).notEmpty(); + req.checkParams('taskId', res.t('taskIdRequired')).notEmpty(); let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; @@ -841,7 +840,7 @@ api.scoreCheckListItem = { async handler (req, res) { let user = res.locals.user; - req.checkParams('taskId', apiMessages('taskIdRequired')).notEmpty(); + req.checkParams('taskId', res.t('taskIdRequired')).notEmpty(); req.checkParams('itemId', res.t('itemIdRequired')).notEmpty().isUUID(); let validationErrors = req.validationErrors(); @@ -891,7 +890,7 @@ api.updateChecklistItem = { let challenge; let group; - req.checkParams('taskId', apiMessages('taskIdRequired')).notEmpty(); + req.checkParams('taskId', res.t('taskIdRequired')).notEmpty(); req.checkParams('itemId', res.t('itemIdRequired')).notEmpty().isUUID(); let validationErrors = req.validationErrors(); @@ -956,7 +955,7 @@ api.removeChecklistItem = { let challenge; let group; - req.checkParams('taskId', apiMessages('taskIdRequired')).notEmpty(); + req.checkParams('taskId', res.t('taskIdRequired')).notEmpty(); req.checkParams('itemId', res.t('itemIdRequired')).notEmpty().isUUID(); let validationErrors = req.validationErrors(); @@ -1017,7 +1016,7 @@ api.addTagToTask = { async handler (req, res) { let user = res.locals.user; - req.checkParams('taskId', apiMessages('taskIdRequired')).notEmpty(); + req.checkParams('taskId', res.t('taskIdRequired')).notEmpty(); let userTags = user.tags.map(tag => tag.id); req.checkParams('tagId', res.t('tagIdRequired')).notEmpty().isUUID().isIn(userTags); @@ -1066,7 +1065,7 @@ api.removeTagFromTask = { async handler (req, res) { let user = res.locals.user; - req.checkParams('taskId', apiMessages('taskIdRequired')).notEmpty(); + req.checkParams('taskId', res.t('taskIdRequired')).notEmpty(); req.checkParams('tagId', res.t('tagIdRequired')).notEmpty().isUUID(); let validationErrors = req.validationErrors(); @@ -1110,7 +1109,7 @@ api.unlinkAllTasks = { middlewares: [authWithHeaders()], async handler (req, res) { req.checkParams('challengeId', res.t('challengeIdRequired')).notEmpty().isUUID(); - req.checkQuery('keep', apiMessages('keepOrRemoveAll')).notEmpty().isIn(['keep-all', 'remove-all']); + req.checkQuery('keep', res.t('keepOrRemoveAll')).notEmpty().isIn(['keep-all', 'remove-all']); let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; @@ -1176,8 +1175,8 @@ api.unlinkOneTask = { url: '/tasks/unlink-one/:taskId', middlewares: [authWithHeaders()], async handler (req, res) { - req.checkParams('taskId', apiMessages('taskIdRequired')).notEmpty().isUUID(); - req.checkQuery('keep', apiMessages('keepOrRemove')).notEmpty().isIn(['keep', 'remove']); + req.checkParams('taskId', res.t('taskIdRequired')).notEmpty().isUUID(); + req.checkQuery('keep', res.t('keepOrRemove')).notEmpty().isIn(['keep', 'remove']); let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; diff --git a/website/server/controllers/api-v3/tasks/groups.js b/website/server/controllers/api-v3/tasks/groups.js index 7cd64e4ef8..45eb8839da 100644 --- a/website/server/controllers/api-v3/tasks/groups.js +++ b/website/server/controllers/api-v3/tasks/groups.js @@ -12,7 +12,6 @@ import { getTasks, moveTask, } from '../../../libs/taskManager'; -import apiMessages from '../../../libs/apiMessages'; let requiredGroupFields = '_id leader tasksOrder name'; let types = Tasks.tasksTypes.map(type => `${type}s`); @@ -41,7 +40,7 @@ api.createGroupTasks = { url: '/tasks/group/:groupId', middlewares: [authWithHeaders()], async handler (req, res) { - req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty().isUUID(); + req.checkParams('groupId', res.t('groupIdRequired')).notEmpty().isUUID(); let reqValidationErrors = req.validationErrors(); if (reqValidationErrors) throw reqValidationErrors; @@ -85,7 +84,7 @@ api.getGroupTasks = { url: '/tasks/group/:groupId', middlewares: [authWithHeaders()], async handler (req, res) { - req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty().isUUID(); + req.checkParams('groupId', res.t('groupIdRequired')).notEmpty().isUUID(); req.checkQuery('type', res.t('invalidTasksType')).optional().isIn(types); let validationErrors = req.validationErrors(); @@ -118,7 +117,7 @@ api.groupMoveTask = { url: '/group-tasks/:taskId/move/to/:position', middlewares: [authWithHeaders()], async handler (req, res) { - req.checkParams('taskId', apiMessages('taskIdRequired')).notEmpty(); + req.checkParams('taskId', res.t('taskIdRequired')).notEmpty(); req.checkParams('position', res.t('positionRequired')).notEmpty().isNumeric(); let reqValidationErrors = req.validationErrors(); @@ -169,7 +168,7 @@ api.assignTask = { url: '/tasks/:taskId/assign/:assignedUserId', middlewares: [authWithHeaders()], async handler (req, res) { - req.checkParams('taskId', apiMessages('taskIdRequired')).notEmpty().isUUID(); + req.checkParams('taskId', res.t('taskIdRequired')).notEmpty().isUUID(); req.checkParams('assignedUserId', res.t('userIdRequired')).notEmpty().isUUID(); let reqValidationErrors = req.validationErrors(); @@ -227,7 +226,7 @@ api.unassignTask = { url: '/tasks/:taskId/unassign/:assignedUserId', middlewares: [authWithHeaders()], async handler (req, res) { - req.checkParams('taskId', apiMessages('taskIdRequired')).notEmpty().isUUID(); + req.checkParams('taskId', res.t('taskIdRequired')).notEmpty().isUUID(); req.checkParams('assignedUserId', res.t('userIdRequired')).notEmpty().isUUID(); let reqValidationErrors = req.validationErrors(); @@ -277,7 +276,7 @@ api.approveTask = { url: '/tasks/:taskId/approve/:userId', middlewares: [authWithHeaders()], async handler (req, res) { - req.checkParams('taskId', apiMessages('taskIdRequired')).notEmpty().isUUID(); + req.checkParams('taskId', res.t('taskIdRequired')).notEmpty().isUUID(); req.checkParams('userId', res.t('userIdRequired')).notEmpty().isUUID(); let reqValidationErrors = req.validationErrors(); @@ -373,7 +372,7 @@ api.taskNeedsWork = { url: '/tasks/:taskId/needs-work/:userId', middlewares: [authWithHeaders()], async handler (req, res) { - req.checkParams('taskId', apiMessages('taskIdRequired')).notEmpty().isUUID(); + req.checkParams('taskId', res.t('taskIdRequired')).notEmpty().isUUID(); req.checkParams('userId', res.t('userIdRequired')).notEmpty().isUUID(); let reqValidationErrors = req.validationErrors(); @@ -470,7 +469,7 @@ api.getGroupApprovals = { url: '/approvals/group/:groupId', middlewares: [authWithHeaders()], async handler (req, res) { - req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty().isUUID(); + req.checkParams('groupId', res.t('groupIdRequired')).notEmpty().isUUID(); let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; diff --git a/website/server/controllers/api-v3/user/spells.js b/website/server/controllers/api-v3/user/spells.js index 98cab96a74..35415137eb 100644 --- a/website/server/controllers/api-v3/user/spells.js +++ b/website/server/controllers/api-v3/user/spells.js @@ -14,7 +14,6 @@ import { castPartySpell, castUserSpell, } from '../../../libs/spells'; -import apiMessages from '../../../libs/apiMessages'; const partyMembersFields = 'profile.name stats achievements items.special'; @@ -86,7 +85,7 @@ api.castSpell = { let klass = common.content.spells.special[spellId] ? 'special' : user.stats.class; let spell = common.content.spells[klass][spellId]; - if (!spell) throw new NotFound(apiMessages('spellNotFound', {spellId})); + if (!spell) throw new NotFound(res.t('spellNotFound', {spellId})); if (spell.mana > user.stats.mp) throw new NotAuthorized(res.t('notEnoughMana')); if (spell.value > user.stats.gp && !spell.previousPurchase) throw new NotAuthorized(res.t('messageNotEnoughGold')); if (spell.lvl > user.stats.lvl) throw new NotAuthorized(res.t('spellLevelTooHigh', {level: spell.lvl})); diff --git a/website/server/controllers/top-level/payments/paypal.js b/website/server/controllers/top-level/payments/paypal.js index 44a130256d..36b7b7a189 100644 --- a/website/server/controllers/top-level/payments/paypal.js +++ b/website/server/controllers/top-level/payments/paypal.js @@ -8,7 +8,8 @@ import { import { BadRequest, } from '../../../libs/errors'; -import apiMessages from '../../../libs/apiMessages'; + +const i18n = shared.i18n; let api = {}; @@ -53,8 +54,8 @@ api.checkoutSuccess = { let gift = req.session.gift ? JSON.parse(req.session.gift) : undefined; delete req.session.gift; - if (!paymentId) throw new BadRequest(apiMessages('missingPaymentId')); - if (!customerId) throw new BadRequest(apiMessages('missingCustomerId')); + if (!paymentId) throw new BadRequest(i18n.t('missingPaymentId')); + if (!customerId) throw new BadRequest(i18n.t('missingCustomerId')); await paypalPayments.checkoutSuccess({user, gift, paymentId, customerId}); @@ -77,7 +78,7 @@ api.subscribe = { url: '/paypal/subscribe', middlewares: [authWithUrl], async handler (req, res) { - if (!req.query.sub) throw new BadRequest(apiMessages('missingSubKey')); + if (!req.query.sub) throw new BadRequest(i18n.t('missingSubKey')); let sub = shared.content.subscriptionBlocks[req.query.sub]; let coupon = req.query.coupon; @@ -108,7 +109,7 @@ api.subscribeSuccess = { async handler (req, res) { let user = res.locals.user; - if (!req.session.paypalBlock) throw new BadRequest(apiMessages('missingPaypalBlock')); + if (!req.session.paypalBlock) throw new BadRequest(i18n.t('missingPaypalBlock')); let block = shared.content.subscriptionBlocks[req.session.paypalBlock]; let groupId = req.session.groupId; diff --git a/website/server/libs/apiMessages.js b/website/server/libs/apiMessages.js index cd6dd7ed54..f368228dbb 100644 --- a/website/server/libs/apiMessages.js +++ b/website/server/libs/apiMessages.js @@ -5,38 +5,12 @@ import _ from 'lodash'; // When this file grows, it can be split into multiple ones. const messages = { - taskIdRequired: 'req.params.taskId must contain a task id.', - keepOrRemove: 'req.query.keep must be either "keep" or "remove".', - keepOrRemoveAll: 'req.query.keep must be either "keep-all" or "remove-all".', - invalidAttribute: '"<%= attr %>" is not a valid Stat.', - - statsObjectRequired: '"stats" update is required', - queryPageInteger: 'req.query.page must be an integer greater than or equal to 0.', - - missingTypeParam: '"req.params.type" is required.', - missingKeyParam: '"req.params.key" is required.', - itemNotFound: 'Item "<%= key %>" not found.', - questNotFound: 'Quest "<%= key %>" not found.', - spellNotFound: 'Skill "<%= spellId %>" not found.', - missingTypeKeyEquip: '"key" and "type" are required parameters.', - invalidTypeEquip: '"type" must be one of "equipped", "pet", "mount", "costume"', - missingPetFoodFeed: '"pet" and "food" are required parameters.', - missingEggHatchingPotion: '"egg" and "hatchingPotion" are required parameters.', - guildsOnlyPaginate: 'Only public guilds support pagination.', guildsPaginateBooleanString: 'req.query.paginate must be a boolean string.', + guildsPageInteger: 'req.query.page must be an integer greater than or equal to 0.', groupIdRequired: 'req.params.groupId must contain a groupId.', - groupRemainOrLeaveChallenges: 'req.query.keep must be either "remain-in-challenges" or "leave-challenges"', managerIdRequired: 'req.body.managerId must contain a user ID.', - noSudoAccess: 'You don\'t have sudo access.', - - eventRequired: '"req.params.event" is required.', - countRequired: '"req.query.count" is required.', - - missingPaymentId: 'Missing "req.query.paymentId"', - missingCustomerId: 'Missing "req.query.customerId"', - missingPaypalBlock: 'Missing "req.session.paypalBlock"', - missingSubKey: 'Missing "req.query.sub"', + noSudoAccess: 'You don\'t have sudo access', }; export default function (msgKey, vars = {}) { diff --git a/website/server/libs/chatReporting/groupChatReporter.js b/website/server/libs/chatReporting/groupChatReporter.js index 583a9f77ff..fc2b61d88d 100644 --- a/website/server/libs/chatReporting/groupChatReporter.js +++ b/website/server/libs/chatReporting/groupChatReporter.js @@ -9,7 +9,6 @@ import { import { getGroupUrl, sendTxn } from '../email'; import slack from '../slack'; import { model as Group } from '../../models/group'; -import apiMessages from '../apiMessages'; const COMMUNITY_MANAGER_EMAIL = nconf.get('EMAILS:COMMUNITY_MANAGER_EMAIL'); const FLAG_REPORT_EMAILS = nconf.get('FLAG_REPORT_EMAIL').split(',').map((email) => { @@ -25,7 +24,7 @@ export default class GroupChatReporter extends ChatReporter { } async validate () { - this.req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); + this.req.checkParams('groupId', this.res.t('groupIdRequired')).notEmpty(); this.req.checkParams('chatId', this.res.t('chatIdRequired')).notEmpty(); let validationErrors = this.req.validationErrors(); diff --git a/website/server/models/webhook.js b/website/server/models/webhook.js index bf4210c8bc..7398592080 100644 --- a/website/server/models/webhook.js +++ b/website/server/models/webhook.js @@ -6,7 +6,6 @@ import {v4 as uuid} from 'uuid'; import _ from 'lodash'; import { BadRequest } from '../libs/errors'; import nconf from 'nconf'; -import apiMessages from '../libs/apiMessages'; const IS_PRODUCTION = nconf.get('IS_PROD'); const Schema = mongoose.Schema; @@ -80,7 +79,7 @@ schema.methods.formatOptions = function formatOptions (res) { this.options = _.pick(this.options, 'groupId'); if (!validator.isUUID(String(this.options.groupId))) { - throw new BadRequest(apiMessages('groupIdRequired')); + throw new BadRequest(res.t('groupIdRequired')); } } };