From a2c183f401bdf8e9abddd35d4561d42034325046 Mon Sep 17 00:00:00 2001 From: enahum Date: Fri, 27 May 2016 09:25:37 -0300 Subject: PLT-1800 Load server side locale from the config.json (#3092) * PLT-1800 Load server side locale from the config.json * Add support for locales with country specifics * Fix localization on served locale file as plain/text --- webapp/components/admin_console/admin_sidebar.jsx | 9 ++ .../admin_console/localization_settings.jsx | 145 +++++++++++++++++++++ .../admin_console/multiselect_settings.jsx | 80 ++++++++++++ webapp/components/root.jsx | 39 +++--- .../user_settings/user_settings_display.jsx | 11 +- 5 files changed, 266 insertions(+), 18 deletions(-) create mode 100644 webapp/components/admin_console/localization_settings.jsx create mode 100644 webapp/components/admin_console/multiselect_settings.jsx (limited to 'webapp/components') diff --git a/webapp/components/admin_console/admin_sidebar.jsx b/webapp/components/admin_console/admin_sidebar.jsx index cdb7e29d5..9548a7763 100644 --- a/webapp/components/admin_console/admin_sidebar.jsx +++ b/webapp/components/admin_console/admin_sidebar.jsx @@ -292,6 +292,15 @@ export default class AdminSidebar extends React.Component { /> } /> + + } + /> { + return {value: locales[l].value, text: locales[l].name}; + }) + }); + } + + canSave() { + return this.state.availableLocales.join(',').indexOf(this.state.defaultClientLocale) !== -1; + } + + getConfigFromState(config) { + config.LocalizationSettings.DefaultServerLocale = this.state.defaultServerLocale; + config.LocalizationSettings.DefaultClientLocale = this.state.defaultClientLocale; + config.LocalizationSettings.AvailableLocales = this.state.availableLocales.join(','); + + return config; + } + + renderTitle() { + return ( +

+ +

+ ); + } + + renderSettings() { + return ( + + } + > + + } + value={this.state.defaultServerLocale} + onChange={this.handleChange} + helpText={ + + } + /> + + } + value={this.state.defaultClientLocale} + onChange={this.handleChange} + helpText={ + + } + /> + + } + selected={this.state.availableLocales} + mustBePresent={this.state.defaultClientLocale} + onChange={this.handleChange} + helpText={ + + } + noResultText={ + + } + errorText={ + + } + notPresent={ + + } + /> + + ); + } +} \ No newline at end of file diff --git a/webapp/components/admin_console/multiselect_settings.jsx b/webapp/components/admin_console/multiselect_settings.jsx new file mode 100644 index 000000000..deba983de --- /dev/null +++ b/webapp/components/admin_console/multiselect_settings.jsx @@ -0,0 +1,80 @@ +// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. +import React from 'react'; +import ReactSelect from 'react-select'; + +import Setting from './setting.jsx'; +import FormError from 'components/form_error.jsx'; + +export default class MultiSelectSetting extends React.Component { + constructor(props) { + super(props); + + this.handleChange = this.handleChange.bind(this); + this.state = {error: false}; + } + + handleChange(newValue) { + const values = newValue.map((n) => { + return n.value; + }); + + if (!newValue || newValue.length === 0) { + this.setState({error: this.props.errorText}); + } else if (this.props.mustBePresent && values.join(',').indexOf(this.props.mustBePresent) === -1) { + this.setState({error: this.props.notPresent}); + } else { + this.props.onChange(this.props.id, values); + this.setState({error: false}); + } + } + + componentWillReceiveProps(newProps) { + if (newProps.mustBePresent && newProps.selected.join(',').indexOf(newProps.mustBePresent) === -1) { + this.setState({error: this.props.notPresent}); + } else { + this.setState({error: false}); + } + } + + render() { + return ( + + + + + ); + } +} + +MultiSelectSetting.defaultProps = { + disabled: false +}; + +MultiSelectSetting.propTypes = { + id: React.PropTypes.string.isRequired, + values: React.PropTypes.array.isRequired, + label: React.PropTypes.node.isRequired, + selected: React.PropTypes.array.isRequired, + mustBePresent: React.PropTypes.string, + onChange: React.PropTypes.func.isRequired, + disabled: React.PropTypes.bool, + helpText: React.PropTypes.node, + noResultText: React.PropTypes.node, + errorText: React.PropTypes.node, + notPresent: React.PropTypes.node +}; \ No newline at end of file diff --git a/webapp/components/root.jsx b/webapp/components/root.jsx index f4656d45f..c8283cbf1 100644 --- a/webapp/components/root.jsx +++ b/webapp/components/root.jsx @@ -6,6 +6,7 @@ import * as GlobalActions from 'actions/global_actions.jsx'; import LocalizationStore from 'stores/localization_store.jsx'; +import Client from 'utils/web_client.jsx'; import {IntlProvider} from 'react-intl'; @@ -26,9 +27,25 @@ export default class Root extends React.Component { this.localizationChanged = this.localizationChanged.bind(this); this.redirectIfNecessary = this.redirectIfNecessary.bind(this); + + // Ya.... + /*eslint-disable */ + if (window.mm_config.SegmentDeveloperKey != null && window.mm_config.SegmentDeveloperKey !== "") { + !function(){var analytics=global.window.analytics=global.window.analytics||[];if(!analytics.initialize)if(analytics.invoked)window.console&&console.error&&console.error("Segment snippet included twice.");else{analytics.invoked=!0;analytics.methods=["trackSubmit","trackClick","trackLink","trackForm","pageview","identify","group","track","ready","alias","page","once","off","on"];analytics.factory=function(t){return function(){var e=Array.prototype.slice.call(arguments);e.unshift(t);analytics.push(e);return analytics}};for(var t=0;t ); } else { - var locale = I18n.getLanguageInfo(this.props.user.locale).name; + let locale; + if (I18n.isLanguageAvailable(userLocale)) { + locale = I18n.getLanguageInfo(userLocale).name; + } else { + locale = I18n.getLanguageInfo(global.window.mm_config.DefaultClientLocale).name; + } languagesSection = (