From f5986c07475e9a6d2cc35da7f4bad78e71aeb89c Mon Sep 17 00:00:00 2001 From: Damian Jansen Date: Fri, 16 Feb 2018 17:50:21 +1000 Subject: [PATCH 1/7] test(unittest): ActivateAction test (#685) * test(unittest): ActivateAction test Changes ActivateAction from a field inject to a constructor inject * test(unittest): Use try-catch instead of expected exception --- .../org/zanata/action/ActivateAction.java | 23 ++- .../org/zanata/action/ActivateActionTest.java | 133 ++++++++++++++++++ 2 files changed, 151 insertions(+), 5 deletions(-) create mode 100644 server/services/src/test/java/org/zanata/action/ActivateActionTest.java diff --git a/server/services/src/main/java/org/zanata/action/ActivateAction.java b/server/services/src/main/java/org/zanata/action/ActivateAction.java index 2bf5a1a9d3..857e3b9417 100644 --- a/server/services/src/main/java/org/zanata/action/ActivateAction.java +++ b/server/services/src/main/java/org/zanata/action/ActivateAction.java @@ -48,21 +48,34 @@ public class ActivateAction implements Serializable { private static final long serialVersionUID = -8079131168179421345L; private static final int LINK_ACTIVE_DAYS = 1; - @Inject + private GroupedConversation conversation; - @Inject private AccountActivationKeyDAO accountActivationKeyDAO; - @Inject private IdentityManager identityManager; - @Inject private UrlUtil urlUtil; - @Inject + private FacesMessages facesMessages; private String activationKey; private HAccountActivationKey key; private String resetPasswordKey; // @Begin(join = true) + @Inject + public ActivateAction(GroupedConversation conversation, + AccountActivationKeyDAO accountActivationKeyDAO, + IdentityManager identityManager, + UrlUtil urlUtil, FacesMessages facesMessages) { + this.conversation = conversation; + this.accountActivationKeyDAO = accountActivationKeyDAO; + this.identityManager = identityManager; + this.urlUtil = urlUtil; + this.facesMessages = facesMessages; + } + + @SuppressWarnings("unused") + public ActivateAction() { + } + public void validateActivationKey() { if (getActivationKey() == null) { throw new KeyNotFoundException("null activation key"); diff --git a/server/services/src/test/java/org/zanata/action/ActivateActionTest.java b/server/services/src/test/java/org/zanata/action/ActivateActionTest.java new file mode 100644 index 0000000000..c370d90e51 --- /dev/null +++ b/server/services/src/test/java/org/zanata/action/ActivateActionTest.java @@ -0,0 +1,133 @@ +/* + * Copyright 2018, Red Hat, Inc. and individual contributors + * as indicated by the @author tags. See the copyright.txt file in the + * distribution for a full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.zanata.action; + +import org.apache.deltaspike.core.api.scope.GroupedConversation; +import org.jglue.cdiunit.InRequestScope; +import org.jglue.cdiunit.InSessionScope; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Answers; +import org.mockito.Mock; +import org.zanata.dao.AccountActivationKeyDAO; +import org.zanata.exception.ActivationLinkExpiredException; +import org.zanata.exception.KeyNotFoundException; +import org.zanata.model.HAccount; +import org.zanata.model.HAccountActivationKey; +import org.zanata.seam.security.IdentityManager; +import org.zanata.test.CdiUnitRunner; +import org.zanata.ui.faces.FacesMessages; +import org.zanata.util.UrlUtil; + +import javax.enterprise.inject.Produces; +import javax.inject.Inject; +import java.util.Date; + +import static org.mockito.Mockito.when; +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author djansen djansen@redhat.com + */ +@InSessionScope +@InRequestScope +@RunWith(CdiUnitRunner.class) +public class ActivateActionTest { + + @Produces + @Mock + private GroupedConversation conversation; + @Produces + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private AccountActivationKeyDAO accountActivationKeyDAO; + @Produces + @Mock + private IdentityManager identityManager; + @Produces + @Mock + private UrlUtil urlUtil; + @Produces + @Mock + private FacesMessages facesMessages; + @Inject + private ActivateAction action; + + @Before + public void before() { + action = new ActivateAction(conversation, accountActivationKeyDAO, + identityManager, urlUtil, facesMessages); + } + + @Test + public void nullKeyTest() { + action.setActivationKey(null); + try { + action.validateActivationKey(); + Assert.fail("Expected KeyNotFoundException"); + } catch (KeyNotFoundException knfe) { + assertThat(knfe.getMessage()).contains("null activation key"); + } + } + + @Test + public void keyNoLongerExists() { + action.setActivationKey("1234567890"); + when(accountActivationKeyDAO.findById(action.getActivationKey(), false)) + .thenReturn(null); + try { + action.validateActivationKey(); + Assert.fail("Expected KeyNotFoundException"); + } catch (KeyNotFoundException knfe) { + assertThat(knfe.getMessage()).contains("activation key: 1234567890"); + } + } + + @Test + public void expiredKeyTest() { + HAccountActivationKey key = new HAccountActivationKey(); + key.setCreationDate(new Date(0L)); + action.setActivationKey("1234567890"); + when(accountActivationKeyDAO.findById(action.getActivationKey(), false)) + .thenReturn(key); + try { + action.validateActivationKey(); + Assert.fail("Expected ActivationLinkExpiredException"); + } catch (ActivationLinkExpiredException alee) { + assertThat(alee.getMessage()) + .contains("Activation link expired:1234567890"); + } + } + + @Test + public void activateTest() { + HAccountActivationKey key = new HAccountActivationKey(); + key.setCreationDate(new Date()); + HAccount hAccount = new HAccount(); + hAccount.setUsername("Aloy"); + action.setActivationKey("1234567890"); + when(accountActivationKeyDAO.findById(action.getActivationKey(), false)) + .thenReturn(key); + action.validateActivationKey(); + // TODO ZNTA-2365 action.activate(); + } +} From 521766d3386d53df33abdc2ca98db9b277ca2c37 Mon Sep 17 00:00:00 2001 From: Damian Jansen Date: Fri, 16 Feb 2018 17:51:10 +1000 Subject: [PATCH 2/7] test(unittest): AdapterUtils unit test (#692) * test(unittest): AdapterUtils unit test * test(unittest): Make AdapterUtils unit test less stringy --- .../org/zanata/adapter/AdapterUtilsTest.java | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 server/services/src/test/java/org/zanata/adapter/AdapterUtilsTest.java diff --git a/server/services/src/test/java/org/zanata/adapter/AdapterUtilsTest.java b/server/services/src/test/java/org/zanata/adapter/AdapterUtilsTest.java new file mode 100644 index 0000000000..6f482b6b31 --- /dev/null +++ b/server/services/src/test/java/org/zanata/adapter/AdapterUtilsTest.java @@ -0,0 +1,66 @@ +/* + * Copyright 2018, Red Hat, Inc. and individual contributors + * as indicated by the @author tags. See the copyright.txt file in the + * distribution for a full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.zanata.adapter; + +import org.junit.Assert; +import org.junit.Test; +import org.zanata.exception.FileFormatAdapterException; + +import java.net.URI; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Damian Jansen djansen@redhat.com + */ +public class AdapterUtilsTest { + + @Test + public void testNull() { + try { + AdapterUtils.readStream(URI.create("")); + Assert.fail("Expected IllegalArgumentException"); + } catch (IllegalArgumentException iae) { + assertThat(iae.getMessage()).contains("absolute"); + } + } + + @Test + public void testMalformed() { + try { + AdapterUtils.readStream(URI + .create("http://2aff:eaff:eaff:7aff:8aff:5aff:faff:eaff:8080/foo")); + Assert.fail("Expected FileFormatAdapterException"); + } catch (FileFormatAdapterException ffae) { + assertThat(ffae.getMessage()).contains("malformed"); + } + } + + @Test + public void testAccess() { + try { + AdapterUtils.readStream(URI.create("http://tmp")); + Assert.fail("Expected FileFormatAdapterException"); + } catch (FileFormatAdapterException ffae) { + assertThat(ffae.getMessage()).contains("stream"); + } + } +} From f8ef325c83855e569ff3bea1954e976e2d6958e1 Mon Sep 17 00:00:00 2001 From: Sean Flanigan Date: Mon, 19 Feb 2018 14:19:56 +1000 Subject: [PATCH 3/7] Update Kotlin to 1.2.21 (#726) --- server/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/pom.xml b/server/pom.xml index 22a4060cfa..b1e67dc429 100644 --- a/server/pom.xml +++ b/server/pom.xml @@ -22,7 +22,7 @@ 2.1.2 10 0 - 1.2.0 + 1.2.21 true 1.8 + + .*[-_\.](alpha|Alpha|ALPHA|b|beta|Beta|BETA|cr|CR|rc|RC|M|EA)[-_\.]?[0-9]* + + diff --git a/parent/pom.xml b/parent/pom.xml index b2583cd3ed..9200c06be4 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -596,7 +596,17 @@ org.codehaus.mojo versions-maven-plugin - 2.2 + 2.5 + + classpath:///zanata-build-tools/versions-rules.xml + + + + org.zanata + build-tools + ${project.version} + + From 5acee19fa70fd94a570626f58163e4e78792c46b Mon Sep 17 00:00:00 2001 From: Sean Flanigan Date: Tue, 20 Feb 2018 17:32:00 +1000 Subject: [PATCH 5/7] Revert "Update Kotlin to 1.2.21" (#728) This reverts commit f8ef325c83855e569ff3bea1954e976e2d6958e1. --- server/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/pom.xml b/server/pom.xml index b1e67dc429..22a4060cfa 100644 --- a/server/pom.xml +++ b/server/pom.xml @@ -22,7 +22,7 @@ 2.1.2 10 0 - 1.2.21 + 1.2.0 true 1.8 + https://oss.sonatype.org/ + + sonatype-staging + + + org.apache.maven.plugins From 1a74f3a033e3d299a42c9b09ab3a79f38d41a0cd Mon Sep 17 00:00:00 2001 From: Earl Floden Date: Wed, 21 Feb 2018 09:15:15 +1000 Subject: [PATCH 7/7] feat(ZNTA-2113) Zanata Frontend Internationalization (#720) * feat(ZNTA-2113): Make react-intl json translation consumable * refactor(ZNTA-2113): Move intl provider inside store * feat(ZNTA-2133): implement fetching react-intl translations action and reducer * fix(ZNTA-2113): use en-us default language * feat(ZNTA-2113): store locale in window config * feat(ZNTA-2113): source config locale in editor get messages from appUrl endpoint save messages to state in reducer update reducer test to also test messages * feat(ZNTA-2113): Dynamicly load language messages, change UI locales if translations exist. Changing the language in the jsf more options page will change the I18n messages to be used in the editor Can be observed for the Japanese language, with the Translating indicator changing * test(ZNTA-2113): update test to use IntlProvider on components with FormattedMessages nb: all components using FormattedMessages will need to update tests likewise * feat(ZNTA-2113): dynamically load the locale data of the selected appLocale * refactor(ZNTA-2113): move DEFAULT_LOCALE to config --- server/zanata-frontend/pom.xml | 1 + server/zanata-frontend/src/app/config.js | 7 +++ .../app/editor/actions/header-action-types.js | 4 ++ .../src/app/editor/actions/header-actions.js | 10 +++ .../src/app/editor/api/index.js | 31 +++++++++- .../TranslatingIndicator.test.js | 19 +++--- .../components/TranslatingIndicator/index.js | 11 ++-- .../src/app/editor/containers/Root/index.js | 62 ++++++++++++------- .../src/app/editor/entrypoint/index.js | 37 ++++------- .../zanata-frontend/src/app/editor/index.html | 3 +- .../app/editor/reducers/context-reducer.js | 2 +- .../editor/reducers/context-reducer.test.js | 2 +- .../editor/reducers/header-data-reducer.js | 9 ++- .../reducers/header-data-reducer.test.js | 26 ++++++-- .../src/app/editor/reducers/index.js | 1 + .../src/app/editor/reducers/ui-reducer.js | 17 ++--- server/zanata-frontend/src/index.html | 1 + .../zanata-frontend/src/messages/en-us.json | 46 +------------- server/zanata-frontend/src/messages/en.json | 6 ++ server/zanata-frontend/src/messages/ja.json | 6 ++ .../webapp/WEB-INF/template/template.xhtml | 1 + .../zanata-war/src/main/webapp/a/index.xhtml | 1 + .../src/main/webapp/editor/index.xhtml | 3 +- 23 files changed, 183 insertions(+), 123 deletions(-) create mode 100644 server/zanata-frontend/src/messages/en.json create mode 100644 server/zanata-frontend/src/messages/ja.json diff --git a/server/zanata-frontend/pom.xml b/server/zanata-frontend/pom.xml index 833dff6616..ad014c5dc8 100644 --- a/server/zanata-frontend/pom.xml +++ b/server/zanata-frontend/pom.xml @@ -133,6 +133,7 @@ src/dist + messages/*.json editor.*.cache.js editor.*.cache.css editor.*.cache.css.map diff --git a/server/zanata-frontend/src/app/config.js b/server/zanata-frontend/src/app/config.js index 2d734e454d..028ff5a369 100644 --- a/server/zanata-frontend/src/app/config.js +++ b/server/zanata-frontend/src/app/config.js @@ -8,6 +8,12 @@ const rawConfig = window.config const config = mapValues(rawConfig || {}, (value) => isJsonString(value) ? JSON.parse(value) : value) +export const DEFAULT_LOCALE = { + localeId: 'en-US', + name: 'English', + isRTL: false +} + // URL this app is deployed to export const appUrl = config.appUrl || '' @@ -27,3 +33,4 @@ export const isAdmin = config.permission : false export const user = config.user export const allowRegister = config.allowRegister || false +export const appLocale = config.appLocale || DEFAULT_LOCALE['localeId'] diff --git a/server/zanata-frontend/src/app/editor/actions/header-action-types.js b/server/zanata-frontend/src/app/editor/actions/header-action-types.js index cb45a1481c..bf36320d1d 100644 --- a/server/zanata-frontend/src/app/editor/actions/header-action-types.js +++ b/server/zanata-frontend/src/app/editor/actions/header-action-types.js @@ -4,8 +4,12 @@ export const TOGGLE_INFO_PANEL = 'TOGGLE_INFO_PANEL' export const TOGGLE_HEADER = 'TOGGLE_HEADER' export const TOGGLE_KEY_SHORTCUTS = 'TOGGLE_KEY_SHORTCUTS' export const UI_LOCALES_FETCHED = 'UI_LOCALES_FETCHED' +export const APP_LOCALE_FETCHED = 'APP_LOCALE_FETCHED' export const CHANGE_UI_LOCALE = 'CHANGE_UI_LOCALE' export const DOCUMENT_SELECTED = 'DOCUMENT_SELECTED' export const LOCALE_SELECTED = 'LOCALE_SELECTED' export const STATS_FETCHED = 'STATS_FETCHED' export const HEADER_DATA_FETCHED = 'HEADER_DATA_FETCHED' +export const LOCALE_MESSAGES_REQUEST = 'LOCALE_MESSAGES_REQUEST' +export const LOCALE_MESSAGES_SUCCESS = 'LOCALE_MESSAGES_SUCCESS' +export const LOCALE_MESSAGES_FAILURE = 'LOCALE_MESSAGES_FAILURE' diff --git a/server/zanata-frontend/src/app/editor/actions/header-actions.js b/server/zanata-frontend/src/app/editor/actions/header-actions.js index 506baf348f..2f5ce77c38 100644 --- a/server/zanata-frontend/src/app/editor/actions/header-actions.js +++ b/server/zanata-frontend/src/app/editor/actions/header-actions.js @@ -2,6 +2,7 @@ import { fetchStatistics, fetchLocales, + fetchI18nLocale, fetchMyInfo, fetchProjectInfo, fetchDocuments, @@ -14,6 +15,7 @@ import { TOGGLE_HEADER, TOGGLE_KEY_SHORTCUTS, UI_LOCALES_FETCHED, + APP_LOCALE_FETCHED, CHANGE_UI_LOCALE, DOCUMENT_SELECTED, LOCALE_SELECTED, @@ -39,6 +41,7 @@ const unwrapResponse = (_dispatch, _errorMsg, response) => { } export const uiLocaleFetched = createAction(UI_LOCALES_FETCHED) +export const appLocaleFetched = createAction(APP_LOCALE_FETCHED) export function fetchUiLocales () { return (dispatch) => { @@ -53,6 +56,13 @@ export function fetchUiLocales () { } } +// fetches react-intl translation json files for app i18n +export function fetchAppLocale (locale) { + return (dispatch) => { + dispatch(fetchI18nLocale(locale)) + } +} + export const changeUiLocale = createAction(CHANGE_UI_LOCALE) const decodeDocId = (docId) => { diff --git a/server/zanata-frontend/src/app/editor/api/index.js b/server/zanata-frontend/src/app/editor/api/index.js index d2d6bc9541..23750e4b19 100644 --- a/server/zanata-frontend/src/app/editor/api/index.js +++ b/server/zanata-frontend/src/app/editor/api/index.js @@ -14,7 +14,15 @@ import { STATUS_APPROVED, STATUS_REJECTED } from '../utils/status-util' -import { apiUrl, serverUrl } from '../../config' +import { + LOCALE_MESSAGES_REQUEST, + LOCALE_MESSAGES_SUCCESS, + LOCALE_MESSAGES_FAILURE +} from '../actions/header-action-types' +import { buildAPIRequest, getJsonHeaders } from '../../actions/common-actions' +import { CALL_API } from 'redux-api-middleware' +import { includes } from 'lodash' +import { apiUrl, serverUrl, appUrl } from '../../config' import stableStringify from 'faster-stable-stringify' export const dashboardUrl = serverUrl + '/dashboard' @@ -52,6 +60,27 @@ export function fetchLocales () { }) } +export function fetchI18nLocale (locale) { + const endpoint = `${appUrl}/messages/${locale}.json` + const apiTypes = [ + LOCALE_MESSAGES_REQUEST, + { + type: LOCALE_MESSAGES_SUCCESS, + payload: (_action, _state, res) => { + const contentType = res.headers.get('Content-Type') + if (contentType && includes(contentType, 'json')) { + return res.json().then((json) => { + return json + }) + } + } + }, + LOCALE_MESSAGES_FAILURE] + return { + [CALL_API]: buildAPIRequest(endpoint, 'GET', getJsonHeaders(), apiTypes) + } +} + export function fetchMyInfo () { const userUrl = `${apiUrl}/user` return fetch(userUrl, { diff --git a/server/zanata-frontend/src/app/editor/components/TranslatingIndicator/TranslatingIndicator.test.js b/server/zanata-frontend/src/app/editor/components/TranslatingIndicator/TranslatingIndicator.test.js index 8f9884dbf7..3c7b3cfef3 100644 --- a/server/zanata-frontend/src/app/editor/components/TranslatingIndicator/TranslatingIndicator.test.js +++ b/server/zanata-frontend/src/app/editor/components/TranslatingIndicator/TranslatingIndicator.test.js @@ -1,27 +1,30 @@ - import React from 'react' import * as ReactDOMServer from 'react-dom/server' import TranslatingIndicator from '.' import { Icon } from '../../../components' import { Row } from 'react-bootstrap' +import { IntlProvider } from 'react-intl' -describe('TranslatingIndicatorTest', () => { - it('TranslatingIndicator markup', () => { +/* global describe expect it */ +describe('TranslatingIndicator', () => { + it('renders default markup', () => { const gettextCatalog = { getString: (key) => { return key } } const actual = ReactDOMServer.renderToStaticMarkup( - ) + + + ) const expected = ReactDOMServer.renderToStaticMarkup( /* eslint-disable max-len */ - diff --git a/server/zanata-frontend/src/app/editor/components/TranslatingIndicator/index.js b/server/zanata-frontend/src/app/editor/components/TranslatingIndicator/index.js index f8aa8dd219..897ef71955 100644 --- a/server/zanata-frontend/src/app/editor/components/TranslatingIndicator/index.js +++ b/server/zanata-frontend/src/app/editor/components/TranslatingIndicator/index.js @@ -23,6 +23,7 @@ import React from 'react' import * as PropTypes from 'prop-types' import { Icon } from '../../../components' import { Row } from 'react-bootstrap' +import { FormattedMessage } from 'react-intl' /** * Indicator that shows 'Translating' when the user is @@ -41,11 +42,13 @@ class TranslatingIndicator extends React.Component { render () { return ( /* eslint-disable max-len */ - diff --git a/server/zanata-frontend/src/app/editor/containers/Root/index.js b/server/zanata-frontend/src/app/editor/containers/Root/index.js index b05f8be711..618e1adae4 100644 --- a/server/zanata-frontend/src/app/editor/containers/Root/index.js +++ b/server/zanata-frontend/src/app/editor/containers/Root/index.js @@ -9,12 +9,15 @@ import EditorHeader from '../EditorHeader' import KeyShortcutCheatSheet from '../KeyShortcutCheatSheet' import KeyShortcutDispatcher from '../KeyShortcutDispatcher' import SuggestionsPanel from '../SuggestionsPanel' -import { getSuggestionsPanelVisible } from '../../reducers' -import { fetchUiLocales } from '../../actions/header-actions' +import { getSuggestionsPanelVisible, getAppLocale } from '../../reducers' +import { fetchUiLocales, fetchAppLocale } from '../../actions/header-actions' import { saveSuggestionPanelHeight } from '../../actions/suggestions-actions' import SplitPane from 'react-split-pane' import { Icons } from '../../../components' import Sidebar from '../Sidebar' +import { locale, formats } from '../../config/intl' +import { appLocale } from '../../../config' +import { IntlProvider } from 'react-intl' /** * Top level of Zanata view hierarchy. @@ -24,7 +27,13 @@ class Root extends Component { percentHeight: PropTypes.number.isRequired, showSuggestion: PropTypes.bool, requestUiLocales: PropTypes.func.isRequired, - saveSuggestionPanelHeight: PropTypes.func.isRequired + requestAppLocale: PropTypes.func.isRequired, + saveSuggestionPanelHeight: PropTypes.func.isRequired, + localeMessages: PropTypes.object + } + + componentWillMount () { + this.props.requestAppLocale() } componentDidMount () { @@ -68,26 +77,31 @@ class Root extends Component { const pixelHeight = this.props.showSuggestion ? this.props.percentHeight * window.innerHeight : 0 - // TODO adjust scrollbar width on div like Angular template editor.html return ( - - - - - - - - {this.props.showSuggestion && } - - - - - + + + + + + + + + {this.props.showSuggestion && } + + + + + + ) } } @@ -97,12 +111,16 @@ function mapStateToProps (state) { return { percentHeight: suggestions.heightPercent, showSidebar: sidebar.visible, - showSuggestion: getSuggestionsPanelVisible(state) + showSuggestion: getSuggestionsPanelVisible(state), + localeMessages: getAppLocale(state) } } function mapDispatchToProps (dispatch) { return { + requestAppLocale: () => { + dispatch(fetchAppLocale(appLocale)) + }, saveSuggestionPanelHeight: (pixelHeight) => { const percent = pixelHeight / window.innerHeight dispatch(saveSuggestionPanelHeight(percent)) diff --git a/server/zanata-frontend/src/app/editor/entrypoint/index.js b/server/zanata-frontend/src/app/editor/entrypoint/index.js index b78cee56b0..83651e9f13 100644 --- a/server/zanata-frontend/src/app/editor/entrypoint/index.js +++ b/server/zanata-frontend/src/app/editor/entrypoint/index.js @@ -3,17 +3,15 @@ import 'babel-polyfill' import React from 'react' import * as ReactDOM from 'react-dom' import { appUrl, serverUrl } from '../../config' -import { locale, formats } from '../config/intl' import createStoreWithMiddleware from '../middlewares' -import { addLocaleData, IntlProvider } from 'react-intl' -import enLocaleData from 'react-intl/locale-data/en.js' +import { addLocaleData } from 'react-intl' import { Provider } from 'react-redux' import { browserHistory, Router, Route } from 'react-router' import { syncHistoryWithStore } from 'react-router-redux' import rootReducer from '../reducers' import addWatchers from '../watchers' import { isEmpty } from 'lodash' - +import { appLocale } from '../../config' import Root from '../containers/Root' import NeedSlugMessage from '../containers/NeedSlugMessage' import { fetchSettings } from '../actions/settings-actions' @@ -36,19 +34,8 @@ import '../index.css' * - ensuring the required css for the React component tree is available */ function runApp () { - // TODO add all the relevant locale data - // Something like: - // import en from './react-intl/locale-data/en' - // import de from './react-intl/locale-data/de' - // ... then just addLocaleData(en) etc. - // See https://github.com/yahoo/react-intl/blob/master/UPGRADE.md - // if ('ReactIntlLocaleData' in window) { - // Object.keys(window.ReactIntlLocaleData).forEach(lang => { - // addLocaleData(window.ReactIntlLocaleData[lang]) - // }) - // } - - addLocaleData([...enLocaleData]) + // Dynamically load the locale data of the selected appLocale + addLocaleData(require(`react-intl/locale-data/${appLocale}`)) const history = browserHistory history.basename = appUrl @@ -75,15 +62,13 @@ function runApp () { // require.ensure and pass to IntlProvider as messages={...} // defaultLocale will use the default messages with no errors ReactDOM.render( - - - - {/* The ** is docId, captured as params.splat by react-router. */} - - - - - , rootElement) + + + {/* The ** is docId, captured as params.splat by react-router. */} + + + + , rootElement) } if (window.Intl) { diff --git a/server/zanata-frontend/src/app/editor/index.html b/server/zanata-frontend/src/app/editor/index.html index 8956f7949c..44d6037baf 100644 --- a/server/zanata-frontend/src/app/editor/index.html +++ b/server/zanata-frontend/src/app/editor/index.html @@ -43,7 +43,8 @@ data-links='{ "loginUrl": "http://localhost:8080/account/sign_in", "registerUrl": "http://localhost:8080/account/register" - }'> + }' + data-app-locale='ja'>