Skip to content

Commit 1f2a0e6

Browse files
committed
fix(translations): Allow changing active language with ?lang=lang_code query argument
1 parent 81e1aaa commit 1f2a0e6

30 files changed

+1771
-1504
lines changed

lib/api-routes/chat-routes.js

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@ const { Account } = require('../account');
55
const getSecret = require('../get-secret');
66
const Boom = require('@hapi/boom');
77
const Joi = require('joi');
8-
const { failAction, getBoolean } = require('../tools');
8+
const { failAction, getBoolean, validationHelper } = require('../tools');
99
const settings = require('../settings');
1010
const util = require('util');
11+
const { joiLocales } = require('../translations');
1112

1213
const LOG_VERBOSE = getBoolean(process.env.EE_OPENAPI_VERBOSE);
1314

@@ -421,15 +422,18 @@ async function init(args) {
421422
account: accountIdSchema.required()
422423
}),
423424

424-
payload: Joi.object({
425-
question: Joi.string()
426-
.trim()
427-
.max(1024)
428-
.example('When did Jason last message me?')
429-
.description('Chat message to use')
430-
.label('ChatMessage')
431-
.required()
432-
}).label('RequestChat')
425+
payload: validationHelper(
426+
joiLocales,
427+
Joi.object({
428+
question: Joi.string()
429+
.trim()
430+
.max(1024)
431+
.example('When did Jason last message me?')
432+
.description('Chat message to use')
433+
.label('ChatMessage')
434+
.required()
435+
}).label('RequestChat')
436+
)
433437
},
434438

435439
response: {
@@ -500,16 +504,19 @@ async function init(args) {
500504

501505
failAction,
502506

503-
payload: Joi.object({
504-
account: accountIdSchema.required(),
505-
question: Joi.string()
506-
.trim()
507-
.max(1024)
508-
.example('When did Jason last message me?')
509-
.description('Chat message to use')
510-
.label('ChatMessage')
511-
.required()
512-
})
507+
payload: validationHelper(
508+
joiLocales,
509+
Joi.object({
510+
account: accountIdSchema.required(),
511+
question: Joi.string()
512+
.trim()
513+
.max(1024)
514+
.example('When did Jason last message me?')
515+
.description('Chat message to use')
516+
.label('ChatMessage')
517+
.required()
518+
})
519+
)
513520
}
514521
}
515522
});

lib/api-routes/template-routes.js

Lines changed: 51 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ const getSecret = require('../get-secret');
66
const { templates } = require('../templates');
77
const Boom = require('@hapi/boom');
88
const Joi = require('joi');
9-
const { failAction } = require('../tools');
9+
const { failAction, validationHelper } = require('../tools');
10+
const { joiLocales } = require('../translations');
1011

1112
const { templateSchemas, accountIdSchema } = require('../schemas');
1213

@@ -76,33 +77,36 @@ async function init(args) {
7677
},
7778
failAction,
7879

79-
payload: Joi.object({
80-
account: Joi.string()
81-
.empty('')
82-
.trim()
83-
.allow(null)
84-
.max(256)
85-
.example('example')
86-
.description('Account ID. Use `null` for public templates.')
87-
.required(),
88-
89-
name: Joi.string().max(256).example('Transaction receipt').description('Name of the template').label('TemplateName').required(),
90-
description: Joi.string()
91-
.allow('')
92-
.max(1024)
93-
.example('Something about the template')
94-
.description('Optional description of the template')
95-
.label('TemplateDescription'),
96-
format: Joi.string().valid('html', 'markdown').default('html').description('Markup language for HTML ("html" or "markdown")'),
97-
content: Joi.object({
98-
subject: templateSchemas.subject,
99-
text: templateSchemas.text,
100-
html: templateSchemas.html,
101-
previewText: templateSchemas.previewText
102-
})
103-
.required()
104-
.label('CreateTemplateContent')
105-
}).label('CreateTemplate')
80+
payload: validationHelper(
81+
joiLocales,
82+
Joi.object({
83+
account: Joi.string()
84+
.empty('')
85+
.trim()
86+
.allow(null)
87+
.max(256)
88+
.example('example')
89+
.description('Account ID. Use `null` for public templates.')
90+
.required(),
91+
92+
name: Joi.string().max(256).example('Transaction receipt').description('Name of the template').label('TemplateName').required(),
93+
description: Joi.string()
94+
.allow('')
95+
.max(1024)
96+
.example('Something about the template')
97+
.description('Optional description of the template')
98+
.label('TemplateDescription'),
99+
format: Joi.string().valid('html', 'markdown').default('html').description('Markup language for HTML ("html" or "markdown")'),
100+
content: Joi.object({
101+
subject: templateSchemas.subject,
102+
text: templateSchemas.text,
103+
html: templateSchemas.html,
104+
previewText: templateSchemas.previewText
105+
})
106+
.required()
107+
.label('CreateTemplateContent')
108+
}).label('CreateTemplate')
109+
)
106110
},
107111

108112
response: {
@@ -168,22 +172,25 @@ async function init(args) {
168172
template: Joi.string().max(256).required().example('example').description('Template ID')
169173
}).label('GetTemplateRequest'),
170174

171-
payload: Joi.object({
172-
name: Joi.string().empty('').max(256).example('Transaction receipt').description('Name of the template').label('TemplateName'),
173-
description: Joi.string()
174-
.allow('')
175-
.max(1024)
176-
.example('Something about the template')
177-
.description('Optional description of the template')
178-
.label('TemplateDescription'),
179-
format: Joi.string().empty('').valid('html', 'markdown').default('html').description('Markup language for HTML ("html" or "markdown")'),
180-
content: Joi.object({
181-
subject: templateSchemas.subject,
182-
text: templateSchemas.text,
183-
html: templateSchemas.html,
184-
previewText: templateSchemas.previewText
185-
}).label('UpdateTemplateContent')
186-
}).label('UpdateTemplate')
175+
payload: validationHelper(
176+
joiLocales,
177+
Joi.object({
178+
name: Joi.string().empty('').max(256).example('Transaction receipt').description('Name of the template').label('TemplateName'),
179+
description: Joi.string()
180+
.allow('')
181+
.max(1024)
182+
.example('Something about the template')
183+
.description('Optional description of the template')
184+
.label('TemplateDescription'),
185+
format: Joi.string().empty('').valid('html', 'markdown').default('html').description('Markup language for HTML ("html" or "markdown")'),
186+
content: Joi.object({
187+
subject: templateSchemas.subject,
188+
text: templateSchemas.text,
189+
html: templateSchemas.html,
190+
previewText: templateSchemas.previewText
191+
}).label('UpdateTemplateContent')
192+
}).label('UpdateTemplate')
193+
)
187194
},
188195

189196
response: {

lib/autodetect-imap-settings.js

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,14 @@ const { parseString: parseXmlCb } = require('xml2js');
66
const util = require('util');
77
const packageData = require('../package.json');
88
const parseXml = util.promisify(parseXmlCb);
9-
const { gt } = require('./translations');
109

1110
const { fetch: fetchCmd } = require('undici');
1211
const { retryAgent } = require('./tools');
1312

1413
const RESOLV_TIMEOUT = 5 * 1000;
1514

1615
// use a function instead of const to prevent translations before locale is set
17-
const getAppPasswords = () => [
16+
const getAppPasswords = gt => [
1817
{
1918
trigger: {
2019
exchange: /\bl\.google\.com$/i
@@ -86,10 +85,10 @@ const getAppPasswords = () => [
8685
}
8786
];
8887

89-
function getAppPassword(email, exchange) {
88+
function getAppPassword(email, exchange, gt) {
9089
let domain = email.split('@').pop().trim().toLowerCase();
9190

92-
for (let appPassword of getAppPasswords()) {
91+
for (let appPassword of getAppPasswords(gt)) {
9392
if (appPassword.trigger.domains && appPassword.trigger.domains.includes(domain)) {
9493
return appPassword.value;
9594
}
@@ -303,7 +302,7 @@ async function resolveUsingSRV(email, domain, source) {
303302
return { smtp, imap, _source: source || 'srv' };
304303
}
305304

306-
async function resolveUsingMX(email, domain) {
305+
async function resolveUsingMX(email, domain, gt) {
307306
domain = domain || email.split('@').pop().trim().toLowerCase();
308307

309308
try {
@@ -506,7 +505,7 @@ async function resolveUsingMX(email, domain) {
506505
};
507506

508507
let accountConfig = await resolveConfig();
509-
let appPassword = getAppPassword(email, exchange);
508+
let appPassword = getAppPassword(email, exchange, gt);
510509

511510
return Object.assign({}, accountConfig, appPassword ? { appPassword } : {});
512511
}
@@ -635,11 +634,11 @@ async function timedFunction(prom, timeout, source) {
635634
});
636635
}
637636

638-
async function resolve(email) {
637+
async function resolver(email, gt) {
639638
let exchange;
640639
try {
641640
// prefer MX based resolver
642-
let res = await timedFunction(resolveUsingMX(email), RESOLV_TIMEOUT, 'mx');
641+
let res = await timedFunction(resolveUsingMX(email, null, gt), RESOLV_TIMEOUT, 'mx');
643642
return res;
644643
} catch (err) {
645644
if (err.exchange) {
@@ -662,7 +661,7 @@ async function resolve(email) {
662661
prom.then(res => {
663662
runCount++;
664663

665-
let appPassword = getAppPassword(email, exchange);
664+
let appPassword = getAppPassword(email, exchange, gt);
666665
if (appPassword) {
667666
res = Object.assign({}, res, { appPassword });
668667
}
@@ -679,8 +678,8 @@ async function resolve(email) {
679678
});
680679
}
681680

682-
async function autodetectImapSettings(email) {
683-
return await resolve(email);
681+
async function autodetectImapSettings(email, gt) {
682+
return await resolver(email, gt);
684683
}
685684

686685
module.exports.autodetectImapSettings = autodetectImapSettings;

0 commit comments

Comments
 (0)