Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Whitelist locales #966

Merged
merged 6 commits into from
Sep 21, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions gsa/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ set (GSA_JS_SRC_FILES
${GSA_SRC_DIR}/src/gmp/locale/date.js
${GSA_SRC_DIR}/src/gmp/locale/detector.js
${GSA_SRC_DIR}/src/gmp/locale/lang.js
${GSA_SRC_DIR}/src/gmp/locale/languages.js
${GSA_SRC_DIR}/src/gmp/locale/index.js
${GSA_SRC_DIR}/src/gmp/log.js
${GSA_SRC_DIR}/src/gmp/model.js
Expand Down
2 changes: 1 addition & 1 deletion gsa/src/gmp/gmp.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ import {getCommands} from './command.js';
import LoginCommand from './commands/login.js';

import {setLocale} from './locale/lang';
import {BROWSER_LANGUAGE} from './locale/detector';
import {BROWSER_LANGUAGE} from './locale/languages';

const log = logger.getLogger('gmp');

Expand Down
27 changes: 9 additions & 18 deletions gsa/src/gmp/locale/__tests__/lang.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,29 +36,20 @@ describe('setLocale tests', () => {
expect(getLocale()).toEqual('de');
});

test('should log error when changing to unkown locale', () => {
const origConsole = global.console;
const testConsole = {
error: jest.fn(),
warn: jest.fn(),
info: jest.fn(),
debug: jest.fn(),
trace: jest.fn(),
};

global.console = testConsole;

test('should allow to use en-US for en', () => {
setLocale('en');
expect(getLocale()).toEqual('en');

expect(testConsole.error).not.toHaveBeenCalled();

setLocale('foo');
expect(getLocale()).toEqual('foo');
setLocale('de-CH');
expect(getLocale()).toEqual('de-CH');
});

expect(testConsole.error).toHaveBeenCalled();
test('should fallback to en for unkown locales', () => {
setLocale('en');
expect(getLocale()).toEqual('en');

global.console = origConsole;
setLocale('foo');
expect(getLocale()).toEqual('en');
});

test('should notify language change listeners', () => {
Expand Down
68 changes: 68 additions & 0 deletions gsa/src/gmp/locale/__tests__/languages.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/* Greenbone Security Assistant
*
* Authors:
* Björn Ricks <[email protected]>
*
* Copyright:
* Copyright (C) 2018 Greenbone Networks GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
import 'core-js/fn/object/keys';
import 'core-js/fn/object/values';

import {isString} from 'gmp/utils/identity';

import Languages, {getLanguageCodes} from '../languages';

describe('Language tests', () => {

test('should contain list of languagegs', () => {
expect(Object.keys(Languages).length).toEqual(11);

let called = false;

for (const lang of Object.values(Languages)) {
called = true;

expect(isString(lang.name)).toEqual(true);
expect(isString(lang.native_name)).toEqual(true);
}

expect(called).toEqual(true);
});

});

describe('getLanguageCodes test', () => {

test('should return list of language codes', () => {
const codes = getLanguageCodes();

expect(codes.length).toEqual(11);

let called = false;

for (const code of codes) {
called = true;
expect(isString(code)).toEqual(true);
}

expect(called).toEqual(true);
});

});

// vim: set ts=2 sw=2 tw=80:
5 changes: 3 additions & 2 deletions gsa/src/gmp/locale/detector.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,14 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
import {BROWSER_LANGUAGE} from './languages';

import logger from '../log';

import {isArray, isDefined} from '../utils/identity';

const log = logger.getLogger('gmp.locale.detector');

export const BROWSER_LANGUAGE = 'Browser Language';

const detectLanguageFromStorage = options => options.storage.locale;

const detectLanguageFromNavigator = () => {
Expand Down
24 changes: 22 additions & 2 deletions gsa/src/gmp/locale/lang.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
import 'core-js/fn/string/includes';
import 'core-js/fn/array/includes';

import i18next from 'i18next';
import XHRBackend from 'i18next-xhr-backend';

Expand All @@ -29,6 +32,8 @@ import {isDefined} from '../utils/identity';

import {setLocale as setDateLocale} from './date';
import Detector from './detector';
import {getLanguageCodes} from './languages';
import {split} from 'gmp/utils/string';

const log = logger.getLogger('gmp.locale.lang');

Expand All @@ -41,17 +46,22 @@ const notifyLanguageChangeListeners = (lang, initial = false) => {
}
};

const fallbackLng = 'en';
const whitelist = getLanguageCodes();

const I18N_OPTIONS = {
storage: global.localStorage,
nsSeparator: false, // don't use a namespace separator in keys
keySeparator: false, // don't use a key separator in keys
fallbackLng: 'en',
fallbackLng,
ns: ['gsa'], // use gsa as namespace
defaultNS: 'gsa',
fallbackNS: 'gsa',
backend: {
loadPath: '/locales/{{ns}}-{{lng}}.json', // e.g. /locales/gsa-en.json
},
whitelist,
nonExplicitWhitelist: true,
};

i18next.on('languageChanged', lang => {
Expand Down Expand Up @@ -103,9 +113,19 @@ export const getLocale = () => currentLocale;
* to start automatic detection.
*/
export const setLocale = lang => {
if (isDefined(lang)) {
const code = lang.includes('-') ? split(lang, '-', 1)[0] : lang;

if (!whitelist.includes(lang) && !whitelist.includes(code)) {
log.warn(`Unknown locale ${lang}. Possible locales are ${whitelist}
Falling back to ${fallbackLng}.`);
lang = fallbackLng;
}
}

i18next.changeLanguage(lang, err => {
if (isDefined(err)) {
log.error('Error while setting language to', lang, err);
log.warn('Error while setting language to', lang, err);
}
});
};
Expand Down
78 changes: 78 additions & 0 deletions gsa/src/gmp/locale/languages.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/* Greenbone Security Assistant
*
* Authors:
* Björn Ricks <[email protected]>
*
* Copyright:
* Copyright (C) 2018 Greenbone Networks GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
import 'core-js/fn/object/keys';

export const BROWSER_LANGUAGE = 'Browser Language';

export const getLanguageCodes = () => Object.keys(Languages);

const Languages = {
ar: {
name: 'Arabic',
native_name: 'العربية',
},
de: {
name: 'German',
native_name: 'Deutsch',
},
en: {
name: 'English',
native_name: 'English',
},
es: {
name: 'Spanish',
native_name: 'español',
},
fr: {
name: 'French',
native_name: 'français',
},
it: {
name: 'Italian',
native_name: 'italiano',
},
ja: {
name: 'Japanese',
native_name: '日本語',
},
'pt-BR': {
name: 'Portuguese (Brazil)',
native_name: 'português (Brasil)',
},
ru: {
name: 'Russian',
native_name: 'ру́сский',
},
tr: {
name: 'Turkish',
native_name: 'Türkçe',
},
'zh-CN': {
name: 'Chinese (China)',
native_name: '中文 (中国)',
},
};

export default Languages;

// vim: set ts=2 sw=2 tw=80:
3 changes: 2 additions & 1 deletion gsa/src/setupTests.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
import 'core-js/fn/string/starts-with';

import {configure} from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
Expand All @@ -29,7 +30,7 @@ import {initLocale} from 'gmp/locale/lang';
class FakeBackend {

read(language, namespace, callback) {
if (language === 'en' || language === 'de') {
if (language.startsWith('en') || language.startsWith('de')) {
// change language by calling the callback functioon
return callback();
}
Expand Down
49 changes: 2 additions & 47 deletions gsa/src/web/utils/languages.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,57 +21,12 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
import {_l} from 'gmp/locale/lang';

import {BROWSER_LANGUAGE} from 'gmp/locale/detector';
import GmpLanguages, {BROWSER_LANGUAGE} from 'gmp/locale/languages';

export {BROWSER_LANGUAGE};

const Languages = {
ar: {
name: 'Arabic',
native_name: 'العربية',
},
de: {
name: 'German',
native_name: 'Deutsch',
},
en: {
name: 'English',
native_name: 'English',
},
es: {
name: 'Spanish',
native_name: 'español',
},
fr: {
name: 'French',
native_name: 'français',
},
it: {
name: 'Italian',
native_name: 'italiano',
},
ja: {
name: 'Japanese',
native_name: '日本語',
},
pt_BR: {
name: 'Portuguese (Brazil)',
native_name: 'português (Brasil)',
},
ru: {
name: 'Russian',
native_name: 'ру́сский',
},
tr: {
name: 'Turkish',
native_name: 'Türkçe',
},
zh_CN: {
name: 'Chinese (China)',
native_name: '中文 (中国)',
},

...GmpLanguages,
[BROWSER_LANGUAGE]: {
name: _l('Browser Language'),
},
Expand Down