Skip to content

Commit

Permalink
[FIX JENKINS-39225] Internationalisation for Blue Ocean and JDL (#556)
Browse files Browse the repository at this point in the history
* [JENKINS-35845] WIP first steps with i18n

* eslint - formating changes and fix offences

* [JENKINS-35845] first basic working version with 2 languages

* [JENKINS-35845] WIP adding patched backend to investigate

* [JENKINS-35845] Assumes jenkinsci/jenkins#2586 to be applied. We know get the translations from the standard jenkins way, but needs changes in the core for now

* [JENKINS-35845] remove testing class

* [JENKINS-35845] WIP fixing integration of jenkins i18n keys with dot in them

* [JENKINS-35845] move i18n to core-js and using it from within web

* [JENKINS-35845] follow jenkins convention/pattern for storing locale

* [JENKINS-35845] WIP implement translation in core-js runbutton and toastUtil. Prefix translations with bo.web. remove sample code

* [JENKINS-35845] WIP starting to translate dashboard

* [JENKINS-35845] WIP added german translation and finished dashboard. Currently working on making moment respect the locale

* [JENKINS-35845] Use latest jdl

* [JENKINS-35845] fix locale retrieval

* [JENKINS-35845] update stories to use the new i18n functions. Create story to test readableDate and timeDuration. In node this works fine now traking down wht not in dashboard

* [JENKINS-35845] Add spanish translations

* [JENKINS-35845] better translation for spanish (thank you @Dario) as well updated some german translations

* [JENKINS-35845] Fix german translations with feedback from @daniel

* [JENKINS-35845] Fix test view and finish translation

* [JENKINS-35845] Fix german translation. fix result views. fix some lint issues.

* [JENKINS-35845] create a compose function to wire different functions together

* [JENKINS-35845] better documentation and remove debug string

* [JENKINS-35845] add documentation about i18n and linking contributing and i18n docu in principal readme.

* [JENKINS-35845] updte docu

* [JENKINS-35845] Pass locale and translation function down the component tree. Fix links to not drop query parameters.

* [JENKINS-35845] Fix links to not drop query

* [JENKINS-35845] use the url config util to get correct path to jenkins

* [JENKINS-35845] WIP security commit - refactor i18n class to support listener and subscribe to i18nChanges. Will allow to drop react specific integration via react-i18next.

* [JENKINS-35845] WIP security commit

* [JENKINS-35845] remove debug statement

* [JENKINS-35845] fix import

* Task/jenkins 35845 i18n key rename (#579)

* [JENKINS-35845] rework i18n keys for home page

* [JENKINS-35845] l10n for activity tab

* [JENKINS-35845] l10n for branches tab

* [JENKINS-35845] l10n for pull requests tab

* [JENKINS-35845] l10n for run details -> pipeline

* [JENKINS-35845] l10n for run details -> changes, tests, artifacts

* [JENKINS-35845] l10n for run details header changes

* [JENKINS-35845] pagination; fix typo causing error

* [JENKINS-35845] order keys

* [JENKINS-35845] WIP security commit to be able to merge master

* eslint - formating changes and fix offences

* [JENKINS-35845] Remove dep to snapshot-jenkins and implement fallback to default values. Fix tests of all related projects.

* [JENKINS-35845] remove duplicate variable

* [JENKINS-35845] fix test by adding polyfy again

* eslint - formating changes and fix offences

* [JENKINS-35845] Fix last test

* [JENKINS-35845] fix tests for dashboard

* [JENKINS-35845] sync version numbers
  • Loading branch information
scherler committed Nov 17, 2016
1 parent 1ce9123 commit ed76c2c
Show file tree
Hide file tree
Showing 61 changed files with 7,733 additions and 5,013 deletions.
15 changes: 13 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ https://jenkins.io/blog/2016/05/26/introducing-blue-ocean/
This is in the main Update Center for Jenkins. Install the plugin called "BlueOcean beta" (and let it install its dependencies). The instructions here are for contributors to Blue Ocean and the morbidly curious. Expect refactoring.


![Pirate logo, because it's ocean and stuff](logo-yarrr.png)
![Pirate logo, because it's ocean and stuff](docu/pix/logo-yarrr.png)
Yarr...

# Modules of note
Expand Down Expand Up @@ -82,7 +82,6 @@ List of browsers where we know Blue Ocean is not yet runnable:

* AmigaOS


# Developing

Follow the steps above for getting it running first.
Expand Down Expand Up @@ -141,6 +140,18 @@ npm i
npm shrinkwrap --dev
```


# Contributing - help wanted

## i18n - Sprechen Sie Deutsch?

We have full i18n support in our plugins. Please read the [i18n documentation](./docu/I18N.md) on how you can provide new translations and how to work with i18n.

## contributing guidelines

Want to get involve with blueocean? See our [contributing guidelines](./CONTRIBUTING.md) for more informations.


# Debug and live reload with IntelliJ
Automatically deploys changes to an instance of blueocean that is run with hpi:run.

Expand Down
2 changes: 1 addition & 1 deletion blueocean-core-js/gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ gulp.task("watch", ["clean-build"], () => {
// Default to all

gulp.task("default", () =>
runSequence("clean", "lint", "test", "build", "validate"));
runSequence("clean", "lint", "build", "validate"));

// Clean and build only, for watching

Expand Down
5 changes: 4 additions & 1 deletion blueocean-core-js/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@jenkins-cd/blueocean-core-js",
"version": "0.0.22",
"version": "0.0.23-unreleased1",
"description": "Shared JavaScript libraries for use with Jenkins Blue Ocean",
"main": "dist/js/index.js",
"scripts": {
Expand Down Expand Up @@ -29,6 +29,9 @@
"es6-promise": "4.0.5",
"eslint": "2.13.1",
"eslint-plugin-react": "4.3.0",
"i18next": "3.5.2",
"i18next-browser-languagedetector": "^1.0.0",
"i18next-xhr-backend": "1.2.0",
"isomorphic-fetch": "2.2.1",
"jsonwebtoken": "7.1.9",
"mobx": "2.6.0",
Expand Down
17 changes: 12 additions & 5 deletions blueocean-core-js/src/js/ToastUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,21 @@
* Created by cmeyers on 9/21/16.
*/

import { ToastService as toastService } from './index';
import { ToastService as toastService, I18n } from './index';
import { buildRunDetailsUrlFromQueue } from './UrlBuilder';

const CAPABILITY_MULTIBRANCH_PIPELINE = 'io.jenkins.blueocean.rest.model.BlueMultiBranchPipeline';
const CAPABILITY_MULTIBRANCH_BRANCH = 'io.jenkins.blueocean.rest.model.BlueBranch';


export default {

/**
*
* @param runnable
* @param runInfo
* @param toastAction
*/
createRunStartedToast: (runnable, runInfo, toastAction) => {
const translate = I18n.getFixedT(I18n.language, 'jenkins.plugins.blueocean.web.Messages');
const isMultiBranch = runnable._capabilities.some(capability => (
[CAPABILITY_MULTIBRANCH_PIPELINE, CAPABILITY_MULTIBRANCH_BRANCH].indexOf(capability) !== -1
));
Expand All @@ -31,10 +30,18 @@ export default {
);

const name = decodeURIComponent(runnable.name);
const text = translate('toast.run.started', {
0: name,
1: runId,
defaultValue: 'Started "{0}" #{1}',
});

const caption = translate('toast.run.open', {
defaultValue: 'Open',
});
toastService.newToast({
text: `Started "${name}" #${runId}`,
action: 'Open',
text,
action: caption,
onActionClick: () => {
if (toastAction) {
toastAction(runDetailsUrl);
Expand Down
31 changes: 21 additions & 10 deletions blueocean-core-js/src/js/components/RunButton.jsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
/**
* Created by cmeyers on 8/26/16.
*/

import React, { Component, PropTypes } from 'react';
import { Icon } from 'react-material-icons-blue';

import { RunApi as runApi } from '../';
import { ToastService as toastService } from '../';
import { ToastUtils } from '../';
import {
RunApi as runApi,
ToastService as toastService,
ToastUtils,
I18n,
} from '../';
import Security from '../security';
const translate = I18n ? I18n.getFixedT(I18n.language, 'jenkins.plugins.blueocean.web.Messages') : function () { };

const { permit } = Security;

Expand Down Expand Up @@ -68,10 +70,13 @@ export class RunButton extends Component {

const name = decodeURIComponent(this.props.runnable.name);
const runId = this.props.latestRun.id;

toastService.newToast({
text: `Stopping "${name}" #${runId}...`,
const text = translate('toast.run.stopping', {
0: name,
1: runId,
defaultValue: 'Stoppping "{0}" #{1}',
});

toastService.newToast({ text });
}

render() {
Expand All @@ -89,8 +94,14 @@ export class RunButton extends Component {
showRunButton = showRunButton && permit(this.props.runnable).start();
showStopButton = showStopButton && permit(this.props.runnable).stop();

const runLabel = this.props.runText || 'Run';
const stopLabel = this.state.stopping ? 'Stopping...' : 'Stop';
const runLabel = this.props.runText || translate('toast.run', {
defaultValue: 'Run',
});
const stopLabel = this.state.stopping ? translate('toast.stopping', {
defaultValue: 'Stopping ...',
}) : translate('toast.stop', {
defaultValue: 'Stop',
});

if (!showRunButton && !showStopButton) {
return null;
Expand Down
80 changes: 80 additions & 0 deletions blueocean-core-js/src/js/i18n/i18n.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import i18next from 'i18next';
import LngDetector from 'i18next-browser-languagedetector';
import XHR from 'i18next-xhr-backend';

import urlConfig from '../urlconfig';

/**
* Init language detector, we are going to use first queryString and then the navigator prefered language
*/
export const defaultLngDetector = new LngDetector(null, {
// order and from where user language should be detected
order: ['querystring', 'navigator'],
// keys or params to lookup language from
lookupQuerystring: 'language',
});
const prefix = urlConfig.getJenkinsRootURL() || '/';

const loadPath = `${prefix}/i18n/resourceBundle?language={lng}&baseName={ns}`;
/**
* configure the backend for our locale
*/
export const defaultXhr = new XHR(null, {
loadPath,
allowMultiLoading: false,
parse: (data) => {
// we need to parse the response and then extract the data since the rest is garbage for us
const response = JSON.parse(data);
return response.data;
},
});

/**
* Our default properties for i18next
* @type {{fallbackLng: string, ns: string[], defaultNS: string, preload: string[], keySeparator: boolean, debug: boolean, load: string, interpolation: {prefix: string, suffix: string, escapeValue: boolean}}}
*/
export const initOptions = {
fallbackLng: 'en',
// have a common namespace used around the full app
ns: ['jenkins.plugins.blueocean.web.Messages', 'jenkins.plugins.blueocean.dashboard.Messages'],
defaultNS: 'jenkins.plugins.blueocean.web.Messages',
preload: ['en'],
keySeparator: false, // we do not have any nested keys in properties files
debug: false,
load: 'all', // --> ['en-US', 'en', 'dev']
interpolation: {
prefix: '{',
suffix: '}',
escapeValue: false, // not needed for react!!
},
};

/**
* Create a instance of i18next and init it
* in case we are in test mode and run unit test, we deliver a i18next instance that are not using any backend nor language detection
* @param backend {object} - the backend we want to use
* @param lngDetector {object} - the component that detects which language we want to display
* @param options {object} - general options for i18next
* @see defaultOptions
*/
export const i18n = (backend = defaultXhr, lngDetector = defaultLngDetector, options = initOptions) => {
if (typeof window === 'undefined') { // eslint-disable-line no-undef
return i18next.init({
lng: 'en',
resources: {
en: {
translation: {
key: 'hello world',
},
},
},
});
}
return i18next
.use(backend)
.use(lngDetector)
.init(options);
};


export default i18n(defaultXhr, defaultLngDetector, initOptions);
3 changes: 3 additions & 0 deletions blueocean-core-js/src/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,6 @@ export { toastService as ToastService };

const runApi = new RunApi();
export { runApi as RunApi };

// export i18n provider
export I18n, { defaultLngDetector, defaultXhr, initOptions, i18n } from './i18n/i18n';
1 change: 0 additions & 1 deletion blueocean-core-js/test/js/components/RunButton-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { RunButton } from '../../../src/js/components/RunButton';

describe('RunButton', () => {
let pipeline;

beforeEach(() => {
pipeline = utils.clone(require('../data/pipeline-1.json'));
});
Expand Down
Loading

0 comments on commit ed76c2c

Please sign in to comment.