diff --git a/src/routes/settings.js b/src/routes/settings.js index 4f2b7b068..b4a6cbd19 100644 --- a/src/routes/settings.js +++ b/src/routes/settings.js @@ -273,6 +273,26 @@ function setSysinfoConfig(req, res, next) { }); } +function getLanguage(req, res, next) { + settings.getLanguage(function (error, language) { + if (error) return next(BoxError.toHttpError(error)); + + next(new HttpSuccess(200, { language })); + }); +} + +function setLanguage(req, res, next) { + assert.strictEqual(typeof req.body, 'object'); + + if (!req.body.language || typeof req.body.language !== 'string') return next(new HttpError(400, 'language is required')); + + settings.setLanguage(req.body.language, function (error) { + if (error) return next(BoxError.toHttpError(error)); + + next(new HttpSuccess(200, {})); + }); +} + function get(req, res, next) { assert.strictEqual(typeof req.params.setting, 'string'); @@ -284,6 +304,7 @@ function get(req, res, next) { case settings.UNSTABLE_APPS_KEY: return getUnstableAppsConfig(req, res, next); case settings.REGISTRY_CONFIG_KEY: return getRegistryConfig(req, res, next); case settings.SYSINFO_CONFIG_KEY: return getSysinfoConfig(req, res, next); + case settings.LANGUAGE_KEY: return getLanguage(req, res, next); case settings.AUTOUPDATE_PATTERN_KEY: return getAutoupdatePattern(req, res, next); case settings.TIME_ZONE_KEY: return getTimeZone(req, res, next); @@ -305,6 +326,7 @@ function set(req, res, next) { case settings.UNSTABLE_APPS_KEY: return setUnstableAppsConfig(req, res, next); case settings.REGISTRY_CONFIG_KEY: return setRegistryConfig(req, res, next); case settings.SYSINFO_CONFIG_KEY: return setSysinfoConfig(req, res, next); + case settings.LANGUAGE_KEY: return setLanguage(req, res, next); case settings.AUTOUPDATE_PATTERN_KEY: return setAutoupdatePattern(req, res, next); case settings.TIME_ZONE_KEY: return setTimeZone(req, res, next); diff --git a/src/routes/test/settings-test.js b/src/routes/test/settings-test.js index a731fed67..77b18498a 100644 --- a/src/routes/test/settings-test.js +++ b/src/routes/test/settings-test.js @@ -382,4 +382,56 @@ describe('Settings API', function () { }); }); }); + + describe('language', function () { + it('can get default language', function (done) { + superagent.get(SERVER_URL + '/api/v1/settings/language') + .query({ access_token: token }) + .end(function (err, res) { + expect(res.statusCode).to.equal(200); + expect(res.body.language).to.equal('en'); + done(); + }); + }); + + it('cannot set language with missing language', function (done) { + superagent.post(SERVER_URL + '/api/v1/settings/language') + .query({ access_token: token }) + .send({ foo: 'bar' }) + .end(function (err, res) { + expect(res.statusCode).to.equal(400); + done(); + }); + }); + + it('cannot set language with invalid language', function (done) { + superagent.post(SERVER_URL + '/api/v1/settings/language') + .query({ access_token: token }) + .send({ language: 'doesnotexist' }) + .end(function (err, res) { + expect(res.statusCode).to.equal(404); + done(); + }); + }); + + it('can set language', function (done) { + superagent.post(SERVER_URL + '/api/v1/settings/language') + .query({ access_token: token }) + .send({ language: 'de' }) + .end(function (err, res) { + expect(res.statusCode).to.equal(200); + done(); + }); + }); + + it('can get language', function (done) { + superagent.get(SERVER_URL + '/api/v1/settings/language') + .query({ access_token: token }) + .end(function (err, res) { + expect(res.statusCode).to.equal(200); + expect(res.body.language).to.equal('de'); + done(); + }); + }); + }); }); diff --git a/src/settings.js b/src/settings.js index 71deb0724..acfcee9d2 100644 --- a/src/settings.js +++ b/src/settings.js @@ -35,6 +35,9 @@ exports = module.exports = { getLicenseKey, setLicenseKey, + getLanguage, + setLanguage, + getCloudronId, setCloudronId, @@ -93,6 +96,7 @@ exports = module.exports = { TIME_ZONE_KEY: 'time_zone', CLOUDRON_NAME_KEY: 'cloudron_name', LICENSE_KEY: 'license_key', + LANGUAGE_KEY: 'language', CLOUDRON_ID_KEY: 'cloudron_id', CLOUDRON_TOKEN_KEY: 'cloudron_token', @@ -141,6 +145,7 @@ let gDefaults = (function () { result[exports.DYNAMIC_DNS_KEY] = false; result[exports.UNSTABLE_APPS_KEY] = true; result[exports.LICENSE_KEY] = ''; + result[exports.LANGUAGE_KEY] = 'en'; result[exports.CLOUDRON_ID_KEY] = ''; result[exports.CLOUDRON_TOKEN_KEY] = ''; result[exports.BACKUP_CONFIG_KEY] = { @@ -197,6 +202,9 @@ let gDefaults = (function () { let gCache = {}; +// Keep in sync with dashboard +const gSupportedLanguages = ['en', 'de', 'fr', 'it']; + function notifyChange(key, value) { assert.strictEqual(typeof key, 'string'); // value is a variant @@ -649,6 +657,32 @@ function setLicenseKey(licenseKey, callback) { }); } +function getLanguage(callback) { + assert.strictEqual(typeof callback, 'function'); + + settingsdb.get(exports.LANGUAGE_KEY, function (error, value) { + if (error && error.reason === BoxError.NOT_FOUND) return callback(null, gDefaults[exports.LANGUAGE_KEY]); + if (error) return callback(error); + + callback(null, value); + }); +} + +function setLanguage(language, callback) { + assert.strictEqual(typeof language, 'string'); + assert.strictEqual(typeof callback, 'function'); + + if (gSupportedLanguages.indexOf(language) === -1) return callback(new BoxError(BoxError.NOT_FOUND)); + + settingsdb.set(exports.LANGUAGE_KEY, language, function (error) { + if (error) return callback(error); + + notifyChange(exports.LANGUAGE_KEY, language); + + callback(null); + }); +} + function getCloudronId(callback) { assert.strictEqual(typeof callback, 'function');