Skip to content
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
4 changes: 4 additions & 0 deletions config/kibana.yml
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,7 @@
# Set the interval in milliseconds to sample system and process performance
# metrics. Minimum is 100ms. Defaults to 5000.
#ops.interval: 5000

# The default locale. This locale can be used in certain circumstances to substitute any missing
# translations.
#i18n.defaultLocale: "en"
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
"@spalger/test-subj-selector": "0.2.1",
"@spalger/ui-ace": "0.2.3",
"JSONStream": "1.1.1",
"accept-language-parser": "1.2.0",
"angular": "1.4.7",
"angular-bootstrap-colorpicker": "3.0.19",
"angular-elastic": "2.5.0",
Expand Down
11 changes: 9 additions & 2 deletions src/core_plugins/kibana/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { resolve } from 'path';

import Promise from 'bluebird';
import { mkdirp as mkdirpNode } from 'mkdirp';

import manageUuid from './server/lib/manage_uuid';
import ingest from './server/routes/api/ingest';
import search from './server/routes/api/search';
Expand All @@ -13,6 +16,7 @@ module.exports = function (kibana) {
const kbnBaseUrl = '/app/kibana';
return new kibana.Plugin({
id: 'kibana',

config: function (Joi) {
return Joi.object({
enabled: Joi.boolean().default(true),
Expand Down Expand Up @@ -100,12 +104,17 @@ module.exports = function (kibana) {
linkToLastSubUrl: false
},
],

injectDefaultVars(server, options) {
return {
kbnIndex: options.index,
kbnBaseUrl
};
},

translations: [
resolve(__dirname, './translations/en.json')
]
},

preInit: async function (server) {
Expand All @@ -128,9 +137,7 @@ module.exports = function (kibana) {
search(server);
settings(server);
scripts(server);

server.expose('systemApi', systemApi);
}
});

};
4 changes: 4 additions & 0 deletions src/core_plugins/kibana/translations/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"UI-WELCOME_MESSAGE": "Loading Kibana",
"UI-WELCOME_ERROR": "Kibana did not load properly. Check the server output for more information."
}
4 changes: 4 additions & 0 deletions src/server/config/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -178,4 +178,8 @@ module.exports = () => Joi.object({
enabled: Joi.boolean().default(true)
}).default(),

i18n: Joi.object({
defaultLocale: Joi.string().default('en'),
}).default(),

}).default();
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"test_plugin_1-NO_SSL": "Dont run the DE dev server using HTTPS",
"test_plugin_1-DEV": "Run the DE server with development mode defaults"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"test_plugin_1-NO_SSL": "Dont run the dev server using HTTPS",
"test_plugin_1-DEV": "Run the server with development mode defaults",
"test_plugin_1-NO_RUN_SERVER": "Dont run the dev server",
"test_plugin_1-HOME": "Run along home now!"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"test_plugin_1-NO_SSL": "Dont run the es-ES dev server using HTTPS! I am regsitered afterwards!"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"test_plugin_1-NO_SSL": "Dont run the DE dev server using HTTPS! I am regsitered afterwards!"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"test_plugin_2-XXXXXX": "This is XXXXXX string",
"test_plugin_2-YYYY_PPPP": "This is YYYY_PPPP string",
"test_plugin_2-FFFFFFFFFFFF": "This is FFFFFFFFFFFF string",
"test_plugin_2-ZZZ": "This is ZZZ string"
}
226 changes: 226 additions & 0 deletions src/ui/i18n/__tests__/i18n.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
import expect from 'expect.js';
import _ from 'lodash';
import { join } from 'path';

import { I18n } from '../';

const FIXTURES = join(__dirname, 'fixtures');

describe('ui/i18n module', function () {

describe('one plugin', function () {

const i18nObj = new I18n();

before('registerTranslations - one plugin', function () {
const pluginName = 'test_plugin_1';
const pluginTranslationPath = join(FIXTURES, 'translations', pluginName);
const translationFiles = [
join(pluginTranslationPath, 'de.json'),
join(pluginTranslationPath, 'en.json')
];
const filesLen = translationFiles.length;
for (let indx = 0; indx < filesLen; indx++) {
i18nObj.registerTranslations(translationFiles[indx]);
}
});

describe('getTranslations', function () {

it('should return the translations for en locale as registered' , function () {
const languageTag = ['en'];
const expectedTranslationJson = {
'test_plugin_1-NO_SSL': 'Dont run the dev server using HTTPS',
'test_plugin_1-DEV': 'Run the server with development mode defaults',
'test_plugin_1-NO_RUN_SERVER': 'Dont run the dev server',
'test_plugin_1-HOME': 'Run along home now!'
};
return checkTranslations(expectedTranslationJson, languageTag, i18nObj);
});

it('should return the translations for de locale as registered' , function () {
const languageTag = ['de'];
const expectedTranslationJson = {
'test_plugin_1-NO_SSL': 'Dont run the DE dev server using HTTPS',
'test_plugin_1-DEV': 'Run the DE server with development mode defaults'
};
return checkTranslations(expectedTranslationJson, languageTag, i18nObj);
});

it('should pick the highest priority language for which translations exist' , function () {
const languageTags = ['es-ES', 'de', 'en'];
const expectedTranslations = {
'test_plugin_1-NO_SSL': 'Dont run the DE dev server using HTTPS',
'test_plugin_1-DEV': 'Run the DE server with development mode defaults',
};
return checkTranslations(expectedTranslations, languageTags, i18nObj);
});

it('should return translations for highest priority locale where best case match is chosen from registered locales' , function () {
const languageTags = ['es', 'de'];
const expectedTranslations = {
'test_plugin_1-NO_SSL': 'Dont run the es-ES dev server using HTTPS! I am regsitered afterwards!'
};
i18nObj.registerTranslations(join(FIXTURES, 'translations', 'test_plugin_1','es-ES.json'));
return checkTranslations(expectedTranslations, languageTags, i18nObj);
});

it('should return an empty object for locales with no translations' , function () {
const languageTags = ['ja-JA', 'fr'];
return checkTranslations({}, languageTags, i18nObj);
});

});

describe('getTranslationsForDefaultLocale', function () {

it('should return translations for default locale which is set to the en locale' , function () {
const i18nObj1 = new I18n('en');
const expectedTranslations = {
'test_plugin_1-NO_SSL': 'Dont run the dev server using HTTPS',
'test_plugin_1-DEV': 'Run the server with development mode defaults',
'test_plugin_1-NO_RUN_SERVER': 'Dont run the dev server',
'test_plugin_1-HOME': 'Run along home now!'
};
i18nObj1.registerTranslations(join(FIXTURES, 'translations', 'test_plugin_1','en.json'));
return checkTranslationsForDefaultLocale(expectedTranslations, i18nObj1);
});

it('should return translations for default locale which is set to the de locale' , function () {
const i18nObj1 = new I18n('de');
const expectedTranslations = {
'test_plugin_1-NO_SSL': 'Dont run the DE dev server using HTTPS',
'test_plugin_1-DEV': 'Run the DE server with development mode defaults',
};
i18nObj1.registerTranslations(join(FIXTURES, 'translations', 'test_plugin_1','de.json'));
return checkTranslationsForDefaultLocale(expectedTranslations, i18nObj1);
});

});

describe('getAllTranslations', function () {

it('should return all translations' , function () {
const expectedTranslations = {
de: {
'test_plugin_1-NO_SSL': 'Dont run the DE dev server using HTTPS',
'test_plugin_1-DEV': 'Run the DE server with development mode defaults'
},
en: {
'test_plugin_1-NO_SSL': 'Dont run the dev server using HTTPS',
'test_plugin_1-DEV': 'Run the server with development mode defaults',
'test_plugin_1-NO_RUN_SERVER': 'Dont run the dev server',
'test_plugin_1-HOME': 'Run along home now!'
},
'es-ES': {
'test_plugin_1-NO_SSL': 'Dont run the es-ES dev server using HTTPS! I am regsitered afterwards!'
}
};
return checkAllTranslations(expectedTranslations, i18nObj);
});

});

});

describe('multiple plugins', function () {

const i18nObj = new I18n();

beforeEach('registerTranslations - multiple plugin', function () {
const pluginTranslationPath = join(FIXTURES, 'translations');
const translationFiles = [
join(pluginTranslationPath, 'test_plugin_1', 'de.json'),
join(pluginTranslationPath, 'test_plugin_1', 'en.json'),
join(pluginTranslationPath, 'test_plugin_2', 'en.json')
];
const filesLen = translationFiles.length;
for (let indx = 0; indx < filesLen; indx++) {
i18nObj.registerTranslations(translationFiles[indx]);
}
});

describe('getTranslations', function () {

it('should return the translations for en locale as registered' , function () {
const languageTag = ['en'];
const expectedTranslationJson = {
'test_plugin_1-NO_SSL': 'Dont run the dev server using HTTPS',
'test_plugin_1-DEV': 'Run the server with development mode defaults',
'test_plugin_1-NO_RUN_SERVER': 'Dont run the dev server',
'test_plugin_1-HOME': 'Run along home now!',
'test_plugin_2-XXXXXX': 'This is XXXXXX string',
'test_plugin_2-YYYY_PPPP': 'This is YYYY_PPPP string',
'test_plugin_2-FFFFFFFFFFFF': 'This is FFFFFFFFFFFF string',
'test_plugin_2-ZZZ': 'This is ZZZ string'
};
return checkTranslations(expectedTranslationJson, languageTag, i18nObj);
});

it('should return the translations for de locale as registered' , function () {
const languageTag = ['de'];
const expectedTranslationJson = {
'test_plugin_1-NO_SSL': 'Dont run the DE dev server using HTTPS',
'test_plugin_1-DEV': 'Run the DE server with development mode defaults'
};
return checkTranslations(expectedTranslationJson, languageTag, i18nObj);
});

it('should return the most recently registered translation for a key that has multiple translations' , function () {
i18nObj.registerTranslations(join(FIXTURES, 'translations', 'test_plugin_2', 'de.json'));
const languageTag = ['de'];
const expectedTranslationJson = {
'test_plugin_1-NO_SSL': 'Dont run the DE dev server using HTTPS! I am regsitered afterwards!',
'test_plugin_1-DEV': 'Run the DE server with development mode defaults'
};
return checkTranslations(expectedTranslationJson, languageTag, i18nObj);
});

});

});

describe('registerTranslations', function () {

const i18nObj = new I18n();

it('should throw error when registering relative path', function () {
return expect(i18nObj.registerTranslations).withArgs('./some/path').to.throwError();
});

it('should throw error when registering empty filename', function () {
return expect(i18nObj.registerTranslations).withArgs('').to.throwError();
});

it('should throw error when registering filename with no extension', function () {
return expect(i18nObj.registerTranslations).withArgs('file1').to.throwError();
});

it('should throw error when registering filename with non JSON extension', function () {
return expect(i18nObj.registerTranslations).withArgs('file1.txt').to.throwError();
});

});

});

function checkTranslations(expectedTranslations, languageTags, i18nObj) {
return i18nObj.getTranslations(...languageTags)
.then(function (actualTranslations) {
expect(_.isEqual(actualTranslations, expectedTranslations)).to.be(true);
});
}

function checkAllTranslations(expectedTranslations, i18nObj) {
return i18nObj.getAllTranslations()
.then(function (actualTranslations) {
expect(_.isEqual(actualTranslations, expectedTranslations)).to.be(true);
});
}

function checkTranslationsForDefaultLocale(expectedTranslations, i18nObj) {
return i18nObj.getTranslationsForDefaultLocale()
.then(function (actualTranslations) {
expect(_.isEqual(actualTranslations, expectedTranslations)).to.be(true);
});
}
Loading