Skip to content
This repository was archived by the owner on Apr 3, 2019. It is now read-only.

Commit 2a5d3d0

Browse files
authored
fix(metrics): log locale instead of accept languages on flow events
#1702 r=vbudhram,vladikoff
1 parent e2942c2 commit 2a5d3d0

File tree

18 files changed

+152
-74
lines changed

18 files changed

+152
-74
lines changed

bin/key_server.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
* License, v. 2.0. If a copy of the MPL was not distributed with this
33
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
44

5+
'use strict'
6+
57
// Only `require()` the newrelic module if explicity enabled.
68
// If required, modules will be instrumented.
79
require('../lib/newrelic')()
@@ -74,7 +76,12 @@ function main() {
7476
log.stat(Password.stat())
7577
}
7678

77-
require('../lib/senders')(config, log)
79+
let translator
80+
require('../lib/senders/translator')(config.i18n.supportedLanguages, config.i18n.defaultLanguage)
81+
.then(result => {
82+
translator = result
83+
return require('../lib/senders')(log, config, translator)
84+
})
7885
.then(
7986
function(result) {
8087
senders = result
@@ -108,7 +115,7 @@ function main() {
108115
config,
109116
customs
110117
)
111-
server = Server.create(log, error, config, routes, db)
118+
server = Server.create(log, error, config, routes, db, translator)
112119

113120
server.start(
114121
function (err) {

lib/metrics/events.js

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ module.exports = log => {
144144

145145
return request.gatherMetricsContext({
146146
event: event,
147-
locale: coalesceLocale(optionalData, request),
147+
locale: marshallLocale(request),
148148
uid: coalesceUid(optionalData, request),
149149
userAgent: request.headers['user-agent']
150150
}).then(data => {
@@ -175,12 +175,10 @@ function optionallySetService (data, request) {
175175
(request.query && request.query.service)
176176
}
177177

178-
function coalesceLocale (data, request) {
179-
if (data && data.locale) {
180-
return data.locale
178+
function marshallLocale (request) {
179+
if (request.app && request.app.locale) {
180+
return `${request.app.locale}${request.app.isLocaleAcceptable ? '' : '.default'}`
181181
}
182-
183-
return request.app && request.app.acceptLanguage
184182
}
185183

186184
function coalesceUid (data, request) {

lib/routes/account.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -221,8 +221,7 @@ module.exports = function (
221221
account = result
222222

223223
return request.emitMetricsEvent('account.created', {
224-
uid: account.uid.toString('hex'),
225-
locale: account.locale
224+
uid: account.uid.toString('hex')
226225
})
227226
}
228227
)

lib/senders/email.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ module.exports = function (log) {
118118
this.supportUrl = config.supportUrl
119119
this.syncUrl = config.syncUrl
120120
this.templates = templates
121-
this.translator = translator
121+
this.translator = translator.getTranslator
122122
this.verificationUrl = config.verificationUrl
123123
this.verifyLoginUrl = config.verifyLoginUrl
124124
}

lib/senders/index.js

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,19 @@ var P = require('../promise')
88
// This indirection exists to accommodate different config properties
99
// in the old auth mailer. If/when the two config files are merged and
1010
// there's nothing left that imports mailer/config, it is safe to merge
11-
// legacy_index.js and this file into one. Be careful not to mix the args
12-
// up when you do that, they expect config and log in a different order.
11+
// legacy_index.js and this file into one.
1312
var createSenders = require('./legacy_index')
1413

15-
module.exports = function (config, log, sender) {
14+
module.exports = function (log, config, translator, sender) {
1615
var defaultLanguage = config.i18n.defaultLanguage
1716

1817
return createSenders(
1918
log,
2019
{
21-
locales: config.i18n.supportedLanguages,
22-
defaultLanguage: defaultLanguage,
2320
mail: config.smtp,
2421
sms: config.sms
2522
},
23+
translator,
2624
sender
2725
)
2826
.then(

lib/senders/legacy_index.js

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,17 @@
66
// Those files should import this module rather than its sibling index.js.
77
// If/when we eliminate the old mailer config and everything is importing
88
// index.js, we can merge this into there and get rid of the indirection.
9-
// Be careful when doing that btw, they expect the log and config arguments
10-
// in a different order.
119

12-
var P = require('../promise')
1310
var createMailer = require('./email')
1411
var createSms = require('./sms')
1512

16-
module.exports = function (log, config, sender) {
13+
module.exports = function (log, config, translator, sender) {
1714
var Mailer = createMailer(log)
18-
return P.all(
19-
[
20-
require('./translator')(config.locales, config.defaultLanguage),
21-
require('./templates')()
22-
]
23-
)
24-
.spread(
25-
function (translator, templates) {
15+
return require('./templates')()
16+
.then(function (templates) {
2617
return {
2718
email: new Mailer(translator, templates, config.mail, sender),
2819
sms: createSms(log, translator, templates, config.sms)
2920
}
30-
}
31-
)
21+
})
3222
}

lib/senders/sms.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ module.exports = function (log, translator, templates, smsConfig) {
9797

9898
return template({
9999
link: smsConfig[templateName + 'Link'],
100-
translator: translator(acceptLanguage)
100+
translator: translator.getTranslator(acceptLanguage)
101101
}).text
102102
}
103103
}

lib/senders/translator.js

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,18 @@ module.exports = function (locales, defaultLanguage) {
4343
languageTranslations[language] = translator
4444
}
4545

46-
return function translator(acceptLanguage) {
47-
var languages = i18n.parseAcceptLanguage(acceptLanguage)
48-
var best = i18n.normalizeLanguage(i18n.bestLanguage(languages, supportedLanguages, defaultLanguage))
46+
return {
47+
getTranslator: function (acceptLanguage) {
48+
return languageTranslations[getLocale(acceptLanguage)]
49+
},
50+
51+
getLocale: getLocale
52+
}
4953

50-
return languageTranslations[best]
54+
function getLocale (acceptLanguage) {
55+
var languages = i18n.parseAcceptLanguage(acceptLanguage)
56+
var bestLanguage = i18n.bestLanguage(languages, supportedLanguages, defaultLanguage)
57+
return i18n.normalizeLanguage(bestLanguage)
5158
}
5259
}
5360
)

lib/server.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ function logEndpointErrors(response, log) {
4343
}
4444
}
4545

46-
function create(log, error, config, routes, db) {
46+
function create(log, error, config, routes, db, translator) {
4747

4848
// Hawk needs to calculate request signatures based on public URL,
4949
// not the local URL to which it is bound.
@@ -284,7 +284,11 @@ function create(log, error, config, routes, db) {
284284
request.app.remoteAddressChain = xff
285285
request.app.clientAddress = xff[clientAddressIndex]
286286

287-
request.app.acceptLanguage = trimLocale(request.headers['accept-language'])
287+
const acceptLanguage = trimLocale(request.headers['accept-language'])
288+
request.app.acceptLanguage = acceptLanguage
289+
const locale = translator.getLocale(acceptLanguage)
290+
request.app.locale = locale
291+
request.app.isLocaleAcceptable = isLocaleAcceptable(locale, acceptLanguage)
288292

289293
if (request.headers.authorization) {
290294
// Log some helpful details for debugging authentication problems.
@@ -341,6 +345,10 @@ function create(log, error, config, routes, db) {
341345
return server
342346
}
343347

348+
function isLocaleAcceptable (locale, acceptLanguage) {
349+
return RegExp(`^(?:.+, *)*${locale}(?:[,-].+)*$`, 'i').test(acceptLanguage)
350+
}
351+
344352
module.exports = {
345353
create: create,
346354
// Functions below exported for testing

scripts/sms/balance.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ if (config.sms.apiKey === NOT_SET || config.sms.apiSecret === NOT_SET) {
1515

1616
const log = require('../../lib/log')(config.log.level, 'sms-balance')
1717

18-
require('../../lib/senders')(config, log)
18+
require('../../lib/senders/translator')(config.i18n.supportedLanguages, config.i18n.defaultLanguage)
19+
.then(translator => {
20+
return require('../../lib/senders')(log, config, translator)
21+
})
1922
.then(senders => {
2023
return senders.sms.balance()
2124
})

scripts/sms/send.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ if (config.sms.apiKey === NOT_SET || config.sms.apiSecret === NOT_SET) {
1616
const args = parseArgs()
1717
const log = require('../../lib/log')(config.log.level, 'send-sms')
1818

19-
require('../../lib/senders')(config, log)
19+
require('../../lib/senders/translator')(config.i18n.supportedLanguages, config.i18n.defaultLanguage)
20+
.then(translator => {
21+
return require('../../lib/senders')(log, config, translator)
22+
})
2023
.then(senders => {
2124
return senders.sms.send.apply(null, args)
2225
})

scripts/write-emails-to-disk.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
*/
2828

2929
var P = require('bluebird')
30-
var config = require('../config')
30+
const config = require('../config').getProperties()
3131
const createSenders = require('../lib/senders')
3232
var fs = require('fs')
3333
const log = require('../lib/senders/legacy_log')(require('../lib/senders/log')('server'))
@@ -52,8 +52,10 @@ var mailSender = {
5252
close: function () {}
5353
}
5454

55-
56-
createSenders(config.getProperties(), log, mailSender)
55+
require('../lib/senders/translator')(config.i18n.supportedLanguages, config.i18n.defaultLanguage)
56+
.then(translator => {
57+
return createSenders(log, config, translator, mailSender)
58+
})
5759
.then((senders) => {
5860
const mailer = senders.email
5961
checkMessageType(mailer, messageToSend)

test/local/lib/mailer_locales.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,20 @@
44

55
'use strict'
66

7+
const ROOT_DIR = '../../..'
8+
79
const assert = require('insist')
8-
var config = require('../../../config/index').getProperties()
9-
var log = {}
10+
const config = require(`${ROOT_DIR}/config/index`).getProperties()
11+
const log = {}
1012

1113
describe('mailer locales', () => {
1214

1315
let mailer
1416
before(() => {
15-
return require('../../../lib/senders')(config, log)
17+
return require(`${ROOT_DIR}/lib/senders/translator`)(config.i18n.supportedLanguages, config.i18n.defaultLanguage)
18+
.then(translator => {
19+
return require(`${ROOT_DIR}/lib/senders`)(log, config, translator)
20+
})
1621
.then(result => {
1722
mailer = result.email
1823
})

test/local/lib/senders/translator.js

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,37 @@
22
* License, v. 2.0. If a copy of the MPL was not distributed with this
33
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
44

5+
'use strict'
6+
57
const assert = require('insist')
68

79
require('../../../../lib/senders/translator')(['en', 'pt_br', 'DE', 'ES_AR', 'ES_cl'], 'en')
8-
.then(
9-
function (translator) {
10-
it(
11-
'translator works with upper and lowercase languages',
12-
function (t) {
13-
var x = translator('PT-br,DE')
14-
assert.equal(x.language, 'pt-BR')
15-
x = translator('bu-ll,es-ar')
16-
assert.equal(x.language, 'es-AR')
17-
x = translator('es-CL')
18-
assert.equal(x.language, 'es-CL')
19-
x = translator('en-US')
20-
assert.equal(x.language, 'en')
21-
x = translator('db-LB') // a locale that does not exist
22-
assert.equal(x.language, 'en')
23-
}
24-
)
25-
}
26-
)
10+
.then(translator => {
11+
it('returns the correct interface', () => {
12+
assert.equal(typeof translator, 'object')
13+
assert.equal(Object.keys(translator).length, 2)
14+
assert.equal(typeof translator.getTranslator, 'function')
15+
assert.equal(typeof translator.getLocale, 'function')
16+
})
17+
18+
it('getTranslator works with upper and lowercase languages', () => {
19+
let x = translator.getTranslator('PT-br,DE')
20+
assert.equal(x.language, 'pt-BR')
21+
x = translator.getTranslator('bu-ll,es-ar')
22+
assert.equal(x.language, 'es-AR')
23+
x = translator.getTranslator('es-CL')
24+
assert.equal(x.language, 'es-CL')
25+
x = translator.getTranslator('en-US')
26+
assert.equal(x.language, 'en')
27+
x = translator.getTranslator('db-LB') // a locale that does not exist
28+
assert.equal(x.language, 'en')
29+
})
30+
31+
it('getLocale works with upper and lowercase languages', () => {
32+
assert.equal(translator.getLocale('PT-br,DE'), 'pt-BR')
33+
assert.equal(translator.getLocale('bu-ll,es-ar'), 'es-AR')
34+
assert.equal(translator.getLocale('es-CL'), 'es-CL')
35+
assert.equal(translator.getLocale('en-US'), 'en')
36+
assert.equal(translator.getLocale('db-LB'), 'en')
37+
})
38+
})

0 commit comments

Comments
 (0)