This is an automated email from the ASF dual-hosted git repository.
johnbodley pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-superset.git
The following commit(s) were added to refs/heads/master by this push:
new 1473e2c Integrate translation module @superset-ui/translation (#6222)
1473e2c is described below
commit 1473e2cced916dfd6fc88f15a3c05ecb6300556b
Author: Krist Wongsuphasawat <[email protected]>
AuthorDate: Tue Oct 30 14:51:44 2018 -0700
Integrate translation module @superset-ui/translation (#6222)
* add translation modules
* Update package.json
* Update instructions in CONTRIBUTING
* Remove old files
* Add new entry point "translation"
* Change imports
* move setupTranslation code
* remove translation from entry
* Update python template
* Refactor utils into smaller, independent files
* Define preamble
* working state
* combine toggleCheckbox with setupApp
* move code block out of document.ready
* move setupClient to preamble
* fix unit tests
* update package version
* delete deletion code
---
CONTRIBUTING.md | 4 +-
superset/assets/package.json | 4 +-
superset/assets/spec/helpers/shim.js | 2 +
.../assets/spec/javascripts/modules/utils_spec.jsx | 41 ------
.../javascripts/utils/getClientErrorObject_spec.js | 41 ++++++
superset/assets/src/CRUD/CollectionTable.jsx | 4 +-
superset/assets/src/SqlLab/App.jsx | 4 +-
superset/assets/src/SqlLab/actions.js | 6 +-
.../src/SqlLab/components/ExploreResultsButton.jsx | 2 +-
.../src/SqlLab/components/HighlightedSql.jsx | 3 +-
.../assets/src/SqlLab/components/QueryHistory.jsx | 2 +-
.../assets/src/SqlLab/components/QuerySearch.jsx | 2 +-
.../assets/src/SqlLab/components/QueryTable.jsx | 4 +-
.../assets/src/SqlLab/components/ResultSet.jsx | 2 +-
.../src/SqlLab/components/RunQueryActionButton.jsx | 3 +-
.../assets/src/SqlLab/components/SaveQuery.jsx | 2 +-
.../src/SqlLab/components/ShareSqlLabQuery.jsx | 4 +-
.../assets/src/SqlLab/components/SouthPane.jsx | 2 +-
.../assets/src/SqlLab/components/SqlEditor.jsx | 3 +-
.../src/SqlLab/components/SqlEditorLeftBar.jsx | 2 +-
.../src/SqlLab/components/TabbedSqlEditors.jsx | 2 +-
.../assets/src/SqlLab/components/TableElement.jsx | 3 +-
.../src/SqlLab/components/TemplateParamsEditor.jsx | 4 +-
superset/assets/src/SqlLab/getInitialState.js | 2 +-
superset/assets/src/SqlLab/reducers.js | 4 +-
superset/assets/src/addSlice/AddSliceContainer.jsx | 2 +-
superset/assets/src/addSlice/App.jsx | 4 +-
superset/assets/src/chart/chartAction.js | 4 +-
superset/assets/src/chart/chartReducer.js | 2 +-
superset/assets/src/common.js | 42 ------
superset/assets/src/components/AlteredSliceTag.jsx | 3 +-
superset/assets/src/components/AsyncSelect.jsx | 2 +-
superset/assets/src/components/CachedLabel.jsx | 2 +-
superset/assets/src/components/CopyToClipboard.jsx | 2 +-
superset/assets/src/components/EditableTitle.jsx | 2 +-
superset/assets/src/components/FaveStar.jsx | 2 +-
.../assets/src/components/RefreshChartOverlay.jsx | 2 +-
superset/assets/src/components/TableLoader.jsx | 2 +-
.../assets/src/components/URLShortLinkButton.jsx | 2 +-
.../assets/src/components/URLShortLinkModal.jsx | 2 +-
superset/assets/src/dashboard/App.jsx | 6 +-
.../assets/src/dashboard/actions/dashboardState.js | 4 +-
.../assets/src/dashboard/actions/datasources.js | 2 +-
.../assets/src/dashboard/actions/sliceEntities.js | 8 +-
.../src/dashboard/components/AddSliceCard.jsx | 2 +-
.../dashboard/components/BuilderComponentPane.jsx | 2 +-
.../assets/src/dashboard/components/CodeModal.jsx | 2 +-
.../assets/src/dashboard/components/CssEditor.jsx | 3 +-
.../assets/src/dashboard/components/Dashboard.jsx | 3 +-
.../dashboard/components/DeleteComponentModal.jsx | 2 +-
.../assets/src/dashboard/components/Header.jsx | 2 +-
.../dashboard/components/HeaderActionsDropdown.jsx | 2 +-
.../src/dashboard/components/MissingChart.jsx | 2 +-
.../dashboard/components/RefreshIntervalModal.jsx | 3 +-
.../assets/src/dashboard/components/SaveModal.jsx | 4 +-
.../assets/src/dashboard/components/SliceAdder.jsx | 2 +-
.../src/dashboard/components/SliceHeader.jsx | 2 +-
.../dashboard/components/SliceHeaderControls.jsx | 4 +-
.../components/gridComponents/new/NewColumn.jsx | 2 +-
.../components/gridComponents/new/NewDivider.jsx | 2 +-
.../components/gridComponents/new/NewHeader.jsx | 2 +-
.../components/gridComponents/new/NewRow.jsx | 2 +-
.../components/gridComponents/new/NewTabs.jsx | 2 +-
.../components/menu/MarkdownModeDropdown.jsx | 2 +-
.../assets/src/dashboard/reducers/sliceEntities.js | 4 +-
.../src/dashboard/util/backgroundStyleOptions.js | 2 +-
.../src/dashboard/util/headerStyleOptions.js | 2 +-
.../assets/src/datasource/DatasourceEditor.jsx | 3 +-
superset/assets/src/datasource/DatasourceModal.jsx | 2 +-
superset/assets/src/explore/App.jsx | 6 +-
.../assets/src/explore/actions/exploreActions.js | 2 +-
.../AdhocFilterEditPopoverSimpleTabContent.jsx | 2 +-
.../AdhocFilterEditPopoverSqlTabContent.jsx | 2 +-
.../explore/components/AdhocMetricEditPopover.jsx | 2 +-
.../src/explore/components/ControlHeader.jsx | 2 +-
.../explore/components/ControlPanelsContainer.jsx | 3 +-
.../src/explore/components/DisplayQueryButton.jsx | 2 +-
.../src/explore/components/EmbedCodeButton.jsx | 3 +-
.../explore/components/ExploreActionButtons.jsx | 3 +-
.../src/explore/components/ExploreChartHeader.jsx | 2 +-
.../src/explore/components/RowCountLabel.jsx | 2 +-
.../assets/src/explore/components/SaveModal.jsx | 4 +-
.../components/controls/AdhocFilterControl.jsx | 2 +-
.../components/controls/AnnotationLayer.jsx | 5 +-
.../components/controls/AnnotationLayerControl.jsx | 4 +-
.../explore/components/controls/BoundsControl.jsx | 2 +-
.../components/controls/DatasourceControl.jsx | 2 +-
.../components/controls/DateFilterControl.jsx | 2 +-
.../explore/components/controls/MetricsControl.jsx | 3 +-
.../components/controls/SelectAsyncControl.jsx | 4 +-
.../explore/components/controls/SelectControl.jsx | 3 +-
.../explore/components/controls/SpatialControl.jsx | 2 +-
.../components/controls/TextAreaControl.jsx | 4 +-
.../explore/components/controls/VizTypeControl.jsx | 3 +-
superset/assets/src/explore/controls.jsx | 2 +-
superset/assets/src/explore/validators.js | 2 +-
superset/assets/src/explore/visTypes.jsx | 3 +-
superset/assets/src/i18n.jsx | 32 -----
superset/assets/src/locales.jsx | 148 ---------------------
superset/assets/src/modules/utils.js | 69 +---------
superset/assets/src/preamble.js | 24 ++++
superset/assets/src/profile/App.jsx | 4 +-
superset/assets/src/profile/components/App.jsx | 3 +-
.../src/profile/components/CreatedContent.jsx | 3 +-
.../assets/src/profile/components/Favorites.jsx | 3 +-
.../assets/src/profile/components/Security.jsx | 2 +-
.../assets/src/profile/components/UserInfo.jsx | 2 +-
superset/assets/src/setup/setupApp.js | 57 ++++++++
superset/assets/src/utils/common.js | 10 +-
superset/assets/src/utils/errorMessages.js | 6 +
superset/assets/src/utils/getClientErrorObject.js | 40 ++++++
.../src/visualizations/EventFlow/EventFlow.jsx | 2 +-
.../src/visualizations/FilterBox/FilterBox.jsx | 2 +-
superset/assets/src/visualizations/PlaySlider.jsx | 7 +-
superset/assets/src/visualizations/nvd3/NVD3Vis.js | 2 +-
superset/assets/src/welcome/App.jsx | 5 +-
superset/assets/src/welcome/DashboardTable.jsx | 4 +-
superset/assets/src/welcome/Welcome.jsx | 2 +-
superset/assets/webpack.config.js | 27 ++--
superset/assets/yarn.lock | 43 ++----
superset/templates/superset/base.html | 12 +-
superset/templates/superset/basic.html | 16 +--
.../templates/superset/partials/_script_tag.html | 2 +-
123 files changed, 360 insertions(+), 552 deletions(-)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index baee1bc..6104c12 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -394,10 +394,10 @@ from flask_babel import lazy_gettext as _
then wrap our translatable strings with it, e.g. `_('Translate me')`. During
extraction, string literals passed to `_` will be added to the generated `.po`
file for each language for later translation.
At runtime, the `_` function will return the translation of the given string
for the current language, or the given string itself if no translation is
available.
-In JavaScript, the technique is similar: we import `t` (simple translation),
`tn` (translation containing a number), and `TCT` (translating entire React
Components).
+In JavaScript, the technique is similar: we import `t` (simple translation),
`tn` (translation containing a number).
```javascript
-import {t, tn, TCT} from locales;
+import {t, tn } from '@superset-ui/translation';
```
### Enabling language selection
diff --git a/superset/assets/package.json b/superset/assets/package.json
index 8293e96..581af12 100644
--- a/superset/assets/package.json
+++ b/superset/assets/package.json
@@ -52,6 +52,7 @@
"@data-ui/theme": "^0.0.62",
"@data-ui/xy-chart": "^0.0.61",
"@superset-ui/core": "^0.0.7",
+ "@superset-ui/translation": "^0.2.1",
"@vx/legend": "^0.0.170",
"@vx/responsive": "0.0.172",
"@vx/scale": "^0.0.165",
@@ -78,7 +79,6 @@
"geojson-extent": "^0.3.2",
"geolib": "^2.0.24",
"immutable": "^3.8.2",
- "jed": "^1.1.1",
"jquery": "3.1.1",
"json-bigint": "^0.3.0",
"lodash": "^4.17.11",
@@ -97,7 +97,6 @@
"react-bootstrap": "^0.31.5",
"react-bootstrap-dialog": "^0.10.0",
"react-bootstrap-slider": "2.1.5",
- "react-bootstrap-table": "^4.3.1",
"react-color": "^2.13.8",
"react-datetime": "^2.14.0",
"react-dnd": "^2.5.4",
@@ -126,7 +125,6 @@
"redux-undo": "^1.0.0-beta9-9-7",
"reselect": "^4.0.0",
"shortid": "^2.2.6",
- "sprintf-js": "^1.1.1",
"srcdoc-polyfill": "^1.0.0",
"supercluster": "^4.1.1",
"underscore": "^1.8.3",
diff --git a/superset/assets/spec/helpers/shim.js
b/superset/assets/spec/helpers/shim.js
index 2884157..a9c2fa9 100644
--- a/superset/assets/spec/helpers/shim.js
+++ b/superset/assets/spec/helpers/shim.js
@@ -4,6 +4,7 @@ import
'abortcontroller-polyfill/dist/abortcontroller-polyfill-only';
import jsdom from 'jsdom';
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
+import { configure as configureTranslation } from '@superset-ui/translation';
import setupSupersetClient from './setupSupersetClient';
@@ -48,4 +49,5 @@ global.window.location = { href: 'about:blank' };
global.window.performance = { now: () => new Date().getTime() };
global.$ = require('jquery')(global.window);
+configureTranslation();
setupSupersetClient();
diff --git a/superset/assets/spec/javascripts/modules/utils_spec.jsx
b/superset/assets/spec/javascripts/modules/utils_spec.jsx
index 46a73ec..d1566c2 100644
--- a/superset/assets/spec/javascripts/modules/utils_spec.jsx
+++ b/superset/assets/spec/javascripts/modules/utils_spec.jsx
@@ -5,7 +5,6 @@ import {
d3TimeFormatPreset,
defaultNumberFormatter,
mainMetric,
- getClientErrorObject,
} from '../../../src/modules/utils';
describe('utils', () => {
@@ -98,44 +97,4 @@ describe('utils', () => {
expect(mainMetric(metrics)).toBe('foo');
});
});
-
- describe('getClientErrorObject', () => {
- it('Returns a Promise', () => {
- const response = getClientErrorObject('error');
- expect(response.constructor === Promise).toBe(true);
- });
-
- it('Returns a Promise that resolves to an object with an error key', () =>
{
- const error = 'error';
-
- return getClientErrorObject(error).then((errorObj) => {
- expect(errorObj).toMatchObject({ error });
- });
- });
-
- it('Handles Response that can be parsed as json', () => {
- const jsonError = { something: 'something', error: 'Error message' };
- const jsonErrorString = JSON.stringify(jsonError);
-
- return getClientErrorObject(new
Response(jsonErrorString)).then((errorObj) => {
- expect(errorObj).toMatchObject(jsonError);
- });
- });
-
- it('Handles Response that can be parsed as text', () => {
- const textError = 'Hello I am a text error';
-
- return getClientErrorObject(new Response(textError)).then((errorObj) => {
- expect(errorObj).toMatchObject({ error: textError });
- });
- });
-
- it('Handles plain text as input', () => {
- const error = 'error';
-
- return getClientErrorObject(error).then((errorObj) => {
- expect(errorObj).toMatchObject({ error });
- });
- });
- });
});
diff --git
a/superset/assets/spec/javascripts/utils/getClientErrorObject_spec.js
b/superset/assets/spec/javascripts/utils/getClientErrorObject_spec.js
new file mode 100644
index 0000000..2f05021
--- /dev/null
+++ b/superset/assets/spec/javascripts/utils/getClientErrorObject_spec.js
@@ -0,0 +1,41 @@
+import getClientErrorObject from '../../../src/utils/getClientErrorObject';
+
+describe('getClientErrorObject()', () => {
+ it('Returns a Promise', () => {
+ const response = getClientErrorObject('error');
+ expect(response.constructor === Promise).toBe(true);
+ });
+
+ it('Returns a Promise that resolves to an object with an error key', () => {
+ const error = 'error';
+
+ return getClientErrorObject(error).then((errorObj) => {
+ expect(errorObj).toMatchObject({ error });
+ });
+ });
+
+ it('Handles Response that can be parsed as json', () => {
+ const jsonError = { something: 'something', error: 'Error message' };
+ const jsonErrorString = JSON.stringify(jsonError);
+
+ return getClientErrorObject(new Response(jsonErrorString)).then((errorObj)
=> {
+ expect(errorObj).toMatchObject(jsonError);
+ });
+ });
+
+ it('Handles Response that can be parsed as text', () => {
+ const textError = 'Hello I am a text error';
+
+ return getClientErrorObject(new Response(textError)).then((errorObj) => {
+ expect(errorObj).toMatchObject({ error: textError });
+ });
+ });
+
+ it('Handles plain text as input', () => {
+ const error = 'error';
+
+ return getClientErrorObject(error).then((errorObj) => {
+ expect(errorObj).toMatchObject({ error });
+ });
+ });
+});
diff --git a/superset/assets/src/CRUD/CollectionTable.jsx
b/superset/assets/src/CRUD/CollectionTable.jsx
index 514f866..f38c3d3 100644
--- a/superset/assets/src/CRUD/CollectionTable.jsx
+++ b/superset/assets/src/CRUD/CollectionTable.jsx
@@ -1,14 +1,12 @@
import React from 'react';
import PropTypes from 'prop-types';
import shortid from 'shortid';
-
+import { t } from '@superset-ui/translation';
import Button from '../components/Button';
import Fieldset from './Fieldset';
import { recurseReactClone } from './utils';
import './styles.css';
-import { t } from '../locales';
-
const propTypes = {
collection: PropTypes.arrayOf(PropTypes.object).isRequired,
itemGenerator: PropTypes.func,
diff --git a/superset/assets/src/SqlLab/App.jsx
b/superset/assets/src/SqlLab/App.jsx
index 37be951..9e242c3 100644
--- a/superset/assets/src/SqlLab/App.jsx
+++ b/superset/assets/src/SqlLab/App.jsx
@@ -9,13 +9,13 @@ import getInitialState from './getInitialState';
import rootReducer from './reducers';
import { initEnhancer } from '../reduxUtils';
import App from './components/App';
-import { appSetup } from '../common';
+import setupApp from '../setup/setupApp';
import './main.less';
import '../../stylesheets/reactable-pagination.css';
import '../components/FilterableTable/FilterableTableStyles.css';
-appSetup();
+setupApp();
const appContainer = document.getElementById('app');
const bootstrapData = JSON.parse(appContainer.getAttribute('data-bootstrap'));
diff --git a/superset/assets/src/SqlLab/actions.js
b/superset/assets/src/SqlLab/actions.js
index 6d2b6af..e869014 100644
--- a/superset/assets/src/SqlLab/actions.js
+++ b/superset/assets/src/SqlLab/actions.js
@@ -1,15 +1,15 @@
import shortid from 'shortid';
import JSONbig from 'json-bigint';
+import { t } from '@superset-ui/translation';
import { SupersetClient } from '@superset-ui/core';
import { now } from '../modules/dates';
-import { t } from '../locales';
import {
addSuccessToast as addSuccessToastAction,
addDangerToast as addDangerToastAction,
addInfoToast as addInfoToastAction,
} from '../messageToasts/actions';
-import { COMMON_ERR_MESSAGES } from '../utils/common';
+import COMMON_ERR_MESSAGES from '../utils/errorMessages';
export const RESET_STATE = 'RESET_STATE';
export const ADD_QUERY_EDITOR = 'ADD_QUERY_EDITOR';
@@ -153,7 +153,7 @@ export function runQuery(query) {
.catch((error) => {
let message = error.error || error.statusText || t('Unknown error');
if (message.includes('CSRF token')) {
- message = COMMON_ERR_MESSAGES.SESSION_TIMED_OUT;
+ message = t(COMMON_ERR_MESSAGES.SESSION_TIMED_OUT);
}
// @TODO how to verify link?
dispatch(queryFailed(query, message, error.link));
diff --git a/superset/assets/src/SqlLab/components/ExploreResultsButton.jsx
b/superset/assets/src/SqlLab/components/ExploreResultsButton.jsx
index 329f731..06cddbc 100644
--- a/superset/assets/src/SqlLab/components/ExploreResultsButton.jsx
+++ b/superset/assets/src/SqlLab/components/ExploreResultsButton.jsx
@@ -5,12 +5,12 @@ import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { Alert } from 'react-bootstrap';
import Dialog from 'react-bootstrap-dialog';
+import { t } from '@superset-ui/translation';
import shortid from 'shortid';
import { exportChart } from '../../explore/exploreUtils';
import * as actions from '../actions';
import InfoTooltipWithTrigger from '../../components/InfoTooltipWithTrigger';
-import { t } from '../../locales';
import Button from '../../components/Button';
const propTypes = {
diff --git a/superset/assets/src/SqlLab/components/HighlightedSql.jsx
b/superset/assets/src/SqlLab/components/HighlightedSql.jsx
index 119e8d3..0cce92d 100644
--- a/superset/assets/src/SqlLab/components/HighlightedSql.jsx
+++ b/superset/assets/src/SqlLab/components/HighlightedSql.jsx
@@ -1,12 +1,11 @@
import React from 'react';
import PropTypes from 'prop-types';
-
import SyntaxHighlighter, { registerLanguage } from
'react-syntax-highlighter/dist/light';
import sql from 'react-syntax-highlighter/dist/languages/hljs/sql';
import github from 'react-syntax-highlighter/dist/styles/hljs/github';
+import { t } from '@superset-ui/translation';
import ModalTrigger from '../../components/ModalTrigger';
-import { t } from '../../locales';
registerLanguage('sql', sql);
diff --git a/superset/assets/src/SqlLab/components/QueryHistory.jsx
b/superset/assets/src/SqlLab/components/QueryHistory.jsx
index 442bc4c..2c246e4 100644
--- a/superset/assets/src/SqlLab/components/QueryHistory.jsx
+++ b/superset/assets/src/SqlLab/components/QueryHistory.jsx
@@ -1,9 +1,9 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Alert } from 'react-bootstrap';
+import { t } from '@superset-ui/translation';
import QueryTable from './QueryTable';
-import { t } from '../../locales';
const propTypes = {
queries: PropTypes.array.isRequired,
diff --git a/superset/assets/src/SqlLab/components/QuerySearch.jsx
b/superset/assets/src/SqlLab/components/QuerySearch.jsx
index 9e92029..62d0255 100644
--- a/superset/assets/src/SqlLab/components/QuerySearch.jsx
+++ b/superset/assets/src/SqlLab/components/QuerySearch.jsx
@@ -2,6 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import { Button } from 'react-bootstrap';
import Select from 'react-select';
+import { t } from '@superset-ui/translation';
import { SupersetClient } from '@superset-ui/core';
import Loading from '../../components/Loading';
@@ -14,7 +15,6 @@ import {
} from '../../modules/dates';
import { STATUS_OPTIONS, TIME_OPTIONS } from '../constants';
import AsyncSelect from '../../components/AsyncSelect';
-import { t } from '../../locales';
const propTypes = {
actions: PropTypes.object.isRequired,
diff --git a/superset/assets/src/SqlLab/components/QueryTable.jsx
b/superset/assets/src/SqlLab/components/QueryTable.jsx
index 9e53963..c4dc6c8 100644
--- a/superset/assets/src/SqlLab/components/QueryTable.jsx
+++ b/superset/assets/src/SqlLab/components/QueryTable.jsx
@@ -1,9 +1,10 @@
import React from 'react';
import PropTypes from 'prop-types';
-
import moment from 'moment';
import { Table } from 'reactable';
import { Label, ProgressBar, Well } from 'react-bootstrap';
+import { t } from '@superset-ui/translation';
+
import Link from './Link';
import ResultSet from './ResultSet';
import ModalTrigger from '../../components/ModalTrigger';
@@ -11,7 +12,6 @@ import HighlightedSql from './HighlightedSql';
import { fDuration } from '../../modules/dates';
import { storeQuery } from '../../utils/common';
import QueryStateLabel from './QueryStateLabel';
-import { t } from '../../locales';
const propTypes = {
columns: PropTypes.array,
diff --git a/superset/assets/src/SqlLab/components/ResultSet.jsx
b/superset/assets/src/SqlLab/components/ResultSet.jsx
index 6fa8200..6b482e4 100644
--- a/superset/assets/src/SqlLab/components/ResultSet.jsx
+++ b/superset/assets/src/SqlLab/components/ResultSet.jsx
@@ -2,13 +2,13 @@ import React from 'react';
import PropTypes from 'prop-types';
import { Alert, Button, ButtonGroup, ProgressBar } from 'react-bootstrap';
import shortid from 'shortid';
+import { t } from '@superset-ui/translation';
import Loading from '../../components/Loading';
import ExploreResultsButton from './ExploreResultsButton';
import HighlightedSql from './HighlightedSql';
import FilterableTable from '../../components/FilterableTable/FilterableTable';
import QueryStateLabel from './QueryStateLabel';
-import { t } from '../../locales';
const propTypes = {
actions: PropTypes.object,
diff --git a/superset/assets/src/SqlLab/components/RunQueryActionButton.jsx
b/superset/assets/src/SqlLab/components/RunQueryActionButton.jsx
index dd1d8b0..a5b8dae 100644
--- a/superset/assets/src/SqlLab/components/RunQueryActionButton.jsx
+++ b/superset/assets/src/SqlLab/components/RunQueryActionButton.jsx
@@ -1,7 +1,8 @@
import React from 'react';
import PropTypes from 'prop-types';
+import { t } from '@superset-ui/translation';
+
import Button from '../../components/Button';
-import { t } from '../../locales';
const propTypes = {
allowAsync: PropTypes.bool.isRequired,
diff --git a/superset/assets/src/SqlLab/components/SaveQuery.jsx
b/superset/assets/src/SqlLab/components/SaveQuery.jsx
index 007fd57..8b2a28c 100644
--- a/superset/assets/src/SqlLab/components/SaveQuery.jsx
+++ b/superset/assets/src/SqlLab/components/SaveQuery.jsx
@@ -1,10 +1,10 @@
import React from 'react';
import PropTypes from 'prop-types';
import { FormControl, FormGroup, Row, Col } from 'react-bootstrap';
+import { t } from '@superset-ui/translation';
import Button from '../../components/Button';
import ModalTrigger from '../../components/ModalTrigger';
-import { t } from '../../locales';
const propTypes = {
defaultLabel: PropTypes.string,
diff --git a/superset/assets/src/SqlLab/components/ShareSqlLabQuery.jsx
b/superset/assets/src/SqlLab/components/ShareSqlLabQuery.jsx
index 55f8c88..f59129b 100644
--- a/superset/assets/src/SqlLab/components/ShareSqlLabQuery.jsx
+++ b/superset/assets/src/SqlLab/components/ShareSqlLabQuery.jsx
@@ -1,12 +1,12 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Popover, OverlayTrigger } from 'react-bootstrap';
+import { t } from '@superset-ui/translation';
import Button from '../../components/Button';
import CopyToClipboard from '../../components/CopyToClipboard';
import { storeQuery } from '../../utils/common';
-import { getClientErrorObject } from '../../modules/utils';
-import { t } from '../../locales';
+import getClientErrorObject from '../../utils/getClientErrorObject';
import withToasts from '../../messageToasts/enhancers/withToasts';
const propTypes = {
diff --git a/superset/assets/src/SqlLab/components/SouthPane.jsx
b/superset/assets/src/SqlLab/components/SouthPane.jsx
index ce81c8d..eddc808 100644
--- a/superset/assets/src/SqlLab/components/SouthPane.jsx
+++ b/superset/assets/src/SqlLab/components/SouthPane.jsx
@@ -4,12 +4,12 @@ import shortid from 'shortid';
import { Alert, Label, Tab, Tabs } from 'react-bootstrap';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
+import { t } from '@superset-ui/translation';
import * as Actions from '../actions';
import QueryHistory from './QueryHistory';
import ResultSet from './ResultSet';
import { STATUS_OPTIONS, STATE_BSSTYLE_MAP } from '../constants';
-import { t } from '../../locales';
/*
editorQueries are queries executed by users passed from SqlEditor component
diff --git a/superset/assets/src/SqlLab/components/SqlEditor.jsx
b/superset/assets/src/SqlLab/components/SqlEditor.jsx
index 7f82e02..e739efa 100644
--- a/superset/assets/src/SqlLab/components/SqlEditor.jsx
+++ b/superset/assets/src/SqlLab/components/SqlEditor.jsx
@@ -14,6 +14,7 @@ import {
Collapse,
} from 'react-bootstrap';
import SplitPane from 'react-split-pane';
+import { t } from '@superset-ui/translation';
import Button from '../../components/Button';
import TemplateParamsEditor from './TemplateParamsEditor';
@@ -26,8 +27,6 @@ import SqlEditorLeftBar from './SqlEditorLeftBar';
import AceEditorWrapper from './AceEditorWrapper';
import { STATE_BSSTYLE_MAP } from '../constants';
import RunQueryActionButton from './RunQueryActionButton';
-import { t } from '../../locales';
-
const propTypes = {
actions: PropTypes.object.isRequired,
diff --git a/superset/assets/src/SqlLab/components/SqlEditorLeftBar.jsx
b/superset/assets/src/SqlLab/components/SqlEditorLeftBar.jsx
index 12530eb..f0b4d1a 100644
--- a/superset/assets/src/SqlLab/components/SqlEditorLeftBar.jsx
+++ b/superset/assets/src/SqlLab/components/SqlEditorLeftBar.jsx
@@ -4,12 +4,12 @@ import { ControlLabel, Button } from 'react-bootstrap';
import { connect } from 'react-redux';
import Select from 'react-virtualized-select';
import createFilterOptions from 'react-select-fast-filter-options';
+import { t } from '@superset-ui/translation';
import { SupersetClient } from '@superset-ui/core';
import TableElement from './TableElement';
import AsyncSelect from '../../components/AsyncSelect';
import RefreshLabel from '../../components/RefreshLabel';
-import { t } from '../../locales';
const propTypes = {
queryEditor: PropTypes.object.isRequired,
diff --git a/superset/assets/src/SqlLab/components/TabbedSqlEditors.jsx
b/superset/assets/src/SqlLab/components/TabbedSqlEditors.jsx
index 9bf3978..43b7354 100644
--- a/superset/assets/src/SqlLab/components/TabbedSqlEditors.jsx
+++ b/superset/assets/src/SqlLab/components/TabbedSqlEditors.jsx
@@ -4,11 +4,11 @@ import { DropdownButton, MenuItem, Tab, Tabs } from
'react-bootstrap';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import URI from 'urijs';
+import { t } from '@superset-ui/translation';
import * as Actions from '../actions';
import SqlEditor from './SqlEditor';
import { areArraysShallowEqual } from '../../reduxUtils';
-import { t } from '../../locales';
import TabStatusIcon from './TabStatusIcon';
const propTypes = {
diff --git a/superset/assets/src/SqlLab/components/TableElement.jsx
b/superset/assets/src/SqlLab/components/TableElement.jsx
index 96fae9b..d87d7e5 100644
--- a/superset/assets/src/SqlLab/components/TableElement.jsx
+++ b/superset/assets/src/SqlLab/components/TableElement.jsx
@@ -1,15 +1,14 @@
import React from 'react';
import PropTypes from 'prop-types';
-
import { ButtonGroup, Collapse, Well } from 'react-bootstrap';
import shortid from 'shortid';
+import { t } from '@superset-ui/translation';
import CopyToClipboard from '../../components/CopyToClipboard';
import Link from './Link';
import ColumnElement from './ColumnElement';
import ModalTrigger from '../../components/ModalTrigger';
import Loading from '../../components/Loading';
-import { t } from '../../locales';
const propTypes = {
table: PropTypes.object,
diff --git a/superset/assets/src/SqlLab/components/TemplateParamsEditor.jsx
b/superset/assets/src/SqlLab/components/TemplateParamsEditor.jsx
index 8a3387a..baed940 100644
--- a/superset/assets/src/SqlLab/components/TemplateParamsEditor.jsx
+++ b/superset/assets/src/SqlLab/components/TemplateParamsEditor.jsx
@@ -1,7 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Badge } from 'react-bootstrap';
-
import AceEditor from 'react-ace';
import 'brace/mode/sql';
import 'brace/mode/json';
@@ -9,10 +8,11 @@ import 'brace/mode/html';
import 'brace/mode/markdown';
import 'brace/theme/textmate';
+import { t } from '@superset-ui/translation';
+
import ModalTrigger from '../../components/ModalTrigger';
import InfoTooltipWithTrigger from '../../components/InfoTooltipWithTrigger';
import Button from '../../components/Button';
-import { t } from '../../locales';
const propTypes = {
onChange: PropTypes.func,
diff --git a/superset/assets/src/SqlLab/getInitialState.js
b/superset/assets/src/SqlLab/getInitialState.js
index aa98bf1..ba984c2 100644
--- a/superset/assets/src/SqlLab/getInitialState.js
+++ b/superset/assets/src/SqlLab/getInitialState.js
@@ -1,5 +1,5 @@
import shortid from 'shortid';
-import { t } from '../locales';
+import { t } from '@superset-ui/translation';
import getToastsFromPyFlashMessages from
'../messageToasts/utils/getToastsFromPyFlashMessages';
export default function getInitialState({ defaultDbId, ...restBootstrapData })
{
diff --git a/superset/assets/src/SqlLab/reducers.js
b/superset/assets/src/SqlLab/reducers.js
index e1640a5..87d0332 100644
--- a/superset/assets/src/SqlLab/reducers.js
+++ b/superset/assets/src/SqlLab/reducers.js
@@ -1,7 +1,8 @@
import { combineReducers } from 'redux';
import shortid from 'shortid';
-import messageToasts from '../messageToasts/reducers';
+import { t } from '@superset-ui/translation';
+import messageToasts from '../messageToasts/reducers';
import getInitialState from './getInitialState';
import * as actions from './actions';
import { now } from '../modules/dates';
@@ -13,7 +14,6 @@ import {
getFromArr,
addToArr,
} from '../reduxUtils';
-import { t } from '../locales';
export const sqlLabReducer = function (state = {}, action) {
const actionHandlers = {
diff --git a/superset/assets/src/addSlice/AddSliceContainer.jsx
b/superset/assets/src/addSlice/AddSliceContainer.jsx
index 0d876af..f46dbad 100644
--- a/superset/assets/src/addSlice/AddSliceContainer.jsx
+++ b/superset/assets/src/addSlice/AddSliceContainer.jsx
@@ -2,8 +2,8 @@ import React from 'react';
import PropTypes from 'prop-types';
import { Button, Panel } from 'react-bootstrap';
import Select from 'react-virtualized-select';
+import { t } from '@superset-ui/translation';
import visTypes from '../explore/visTypes';
-import { t } from '../locales';
const propTypes = {
datasources: PropTypes.arrayOf(PropTypes.shape({
diff --git a/superset/assets/src/addSlice/App.jsx
b/superset/assets/src/addSlice/App.jsx
index 56469cc..34154a9 100644
--- a/superset/assets/src/addSlice/App.jsx
+++ b/superset/assets/src/addSlice/App.jsx
@@ -1,9 +1,9 @@
import React from 'react';
import { hot } from 'react-hot-loader';
-import { appSetup } from '../common';
+import setupApp from '../setup/setupApp';
import AddSliceContainer from './AddSliceContainer';
-appSetup();
+setupApp();
const addSliceContainer = document.getElementById('js-add-slice-container');
const bootstrapData =
JSON.parse(addSliceContainer.getAttribute('data-bootstrap'));
diff --git a/superset/assets/src/chart/chartAction.js
b/superset/assets/src/chart/chartAction.js
index c26814e..5d5ae24 100644
--- a/superset/assets/src/chart/chartAction.js
+++ b/superset/assets/src/chart/chartAction.js
@@ -1,13 +1,13 @@
/* global window, AbortController */
/* eslint no-undef: 'error' */
+import { t } from '@superset-ui/translation';
import { SupersetClient } from '@superset-ui/core';
import { getExploreUrlAndPayload, getAnnotationJsonUrl } from
'../explore/exploreUtils';
import { requiresQuery, ANNOTATION_SOURCE_TYPES } from
'../modules/AnnotationTypes';
import { addDangerToast } from '../messageToasts/actions';
import { Logger, LOG_ACTIONS_LOAD_CHART } from '../logger';
-import { getClientErrorObject } from '../modules/utils';
import { TIME_RANGE_SEPARATOR } from '../utils/common';
-import { t } from '../locales';
+import getClientErrorObject from '../utils/getClientErrorObject';
export const CHART_UPDATE_STARTED = 'CHART_UPDATE_STARTED';
export function chartUpdateStarted(queryController, latestQueryFormData, key) {
diff --git a/superset/assets/src/chart/chartReducer.js
b/superset/assets/src/chart/chartReducer.js
index 65df6e5..f6b608c 100644
--- a/superset/assets/src/chart/chartReducer.js
+++ b/superset/assets/src/chart/chartReducer.js
@@ -1,7 +1,7 @@
/* eslint camelcase: 0 */
+import { t } from '@superset-ui/translation';
import { now } from '../modules/dates';
import * as actions from './chartAction';
-import { t } from '../locales';
export const chart = {
id: 0,
diff --git a/superset/assets/src/common.js b/superset/assets/src/common.js
deleted file mode 100644
index 2dc0488..0000000
--- a/superset/assets/src/common.js
+++ /dev/null
@@ -1,42 +0,0 @@
-/* eslint global-require: 0 */
-import $ from 'jquery';
-import 'abortcontroller-polyfill/dist/abortcontroller-polyfill-only';
-import { SupersetClient } from '@superset-ui/core';
-import { toggleCheckbox } from './modules/utils';
-import setupClient from './setup/setupClient';
-import setupColors from './setup/setupColors';
-import setupPlugins from './setup/setupPlugins';
-
-setupColors();
-setupPlugins();
-
-$(document).ready(function () {
- $(':checkbox[data-checkbox-api-prefix]').change(function () {
- const $this = $(this);
- const prefix = $this.data('checkbox-api-prefix');
- const id = $this.attr('id');
- toggleCheckbox(prefix, '#' + id);
- });
-
- // for language picker dropdown
- $('#language-picker a').click(function (ev) {
- ev.preventDefault();
- SupersetClient.get({
- endpoint: ev.currentTarget.getAttribute('href'),
- parseMethod: null,
- })
- .then(() => {
- location.reload();
- });
- });
-});
-
-export function appSetup() {
- setupClient();
-
- // A set of hacks to allow apps to run within a FAB template
- // this allows for the server side generated menus to function
- window.$ = $;
- window.jQuery = $;
- require('bootstrap');
-}
diff --git a/superset/assets/src/components/AlteredSliceTag.jsx
b/superset/assets/src/components/AlteredSliceTag.jsx
index a0c1f1e..bfde6f6 100644
--- a/superset/assets/src/components/AlteredSliceTag.jsx
+++ b/superset/assets/src/components/AlteredSliceTag.jsx
@@ -2,11 +2,10 @@ import React from 'react';
import PropTypes from 'prop-types';
import { Table, Tr, Td, Thead, Th } from 'reactable';
import { isEqual, isEmpty } from 'lodash';
-
+import { t } from '@superset-ui/translation';
import TooltipWrapper from './TooltipWrapper';
import { controls } from '../explore/controls';
import ModalTrigger from './ModalTrigger';
-import { t } from '../locales';
const propTypes = {
origFormData: PropTypes.object.isRequired,
diff --git a/superset/assets/src/components/AsyncSelect.jsx
b/superset/assets/src/components/AsyncSelect.jsx
index 4c2ae81..579535f 100644
--- a/superset/assets/src/components/AsyncSelect.jsx
+++ b/superset/assets/src/components/AsyncSelect.jsx
@@ -1,8 +1,8 @@
import React from 'react';
import PropTypes from 'prop-types';
import Select from 'react-select';
+import { t } from '@superset-ui/translation';
import { SupersetClient } from '@superset-ui/core';
-import { t } from '../locales';
const propTypes = {
dataEndpoint: PropTypes.string.isRequired,
diff --git a/superset/assets/src/components/CachedLabel.jsx
b/superset/assets/src/components/CachedLabel.jsx
index 9bfd037..845eac5 100644
--- a/superset/assets/src/components/CachedLabel.jsx
+++ b/superset/assets/src/components/CachedLabel.jsx
@@ -2,8 +2,8 @@ import React from 'react';
import PropTypes from 'prop-types';
import { Label } from 'react-bootstrap';
import moment from 'moment';
+import { t } from '@superset-ui/translation';
import TooltipWrapper from './TooltipWrapper';
-import { t } from '../locales';
const propTypes = {
onClick: PropTypes.func,
diff --git a/superset/assets/src/components/CopyToClipboard.jsx
b/superset/assets/src/components/CopyToClipboard.jsx
index c2b9c57..199e8d4 100644
--- a/superset/assets/src/components/CopyToClipboard.jsx
+++ b/superset/assets/src/components/CopyToClipboard.jsx
@@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Tooltip, OverlayTrigger, MenuItem } from 'react-bootstrap';
-import { t } from '../locales';
+import { t } from '@superset-ui/translation';
const propTypes = {
copyNode: PropTypes.node,
diff --git a/superset/assets/src/components/EditableTitle.jsx
b/superset/assets/src/components/EditableTitle.jsx
index a3df712..4d71ac7 100644
--- a/superset/assets/src/components/EditableTitle.jsx
+++ b/superset/assets/src/components/EditableTitle.jsx
@@ -1,8 +1,8 @@
import React from 'react';
import PropTypes from 'prop-types';
import cx from 'classnames';
+import { t } from '@superset-ui/translation';
import TooltipWrapper from './TooltipWrapper';
-import { t } from '../locales';
const propTypes = {
title: PropTypes.string,
diff --git a/superset/assets/src/components/FaveStar.jsx
b/superset/assets/src/components/FaveStar.jsx
index 60de9d1..cba83db 100644
--- a/superset/assets/src/components/FaveStar.jsx
+++ b/superset/assets/src/components/FaveStar.jsx
@@ -1,8 +1,8 @@
import React from 'react';
import PropTypes from 'prop-types';
import cx from 'classnames';
+import { t } from '@superset-ui/translation';
import TooltipWrapper from './TooltipWrapper';
-import { t } from '../locales';
const propTypes = {
itemId: PropTypes.number.isRequired,
diff --git a/superset/assets/src/components/RefreshChartOverlay.jsx
b/superset/assets/src/components/RefreshChartOverlay.jsx
index 9e3fced..841559a 100644
--- a/superset/assets/src/components/RefreshChartOverlay.jsx
+++ b/superset/assets/src/components/RefreshChartOverlay.jsx
@@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
+import { t } from '@superset-ui/translation';
import Button from '../components/Button';
-import { t } from '../locales';
const propTypes = {
height: PropTypes.number.isRequired,
diff --git a/superset/assets/src/components/TableLoader.jsx
b/superset/assets/src/components/TableLoader.jsx
index 2f57ab8..0d31934 100644
--- a/superset/assets/src/components/TableLoader.jsx
+++ b/superset/assets/src/components/TableLoader.jsx
@@ -1,10 +1,10 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Table, Tr, Td } from 'reactable';
+import { t } from '@superset-ui/translation';
import { SupersetClient } from '@superset-ui/core';
import withToasts from '../messageToasts/enhancers/withToasts';
-import { t } from '../locales';
import Loading from '../components/Loading';
import '../../stylesheets/reactable-pagination.css';
diff --git a/superset/assets/src/components/URLShortLinkButton.jsx
b/superset/assets/src/components/URLShortLinkButton.jsx
index 47fd332..c2072db 100644
--- a/superset/assets/src/components/URLShortLinkButton.jsx
+++ b/superset/assets/src/components/URLShortLinkButton.jsx
@@ -1,9 +1,9 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Popover, OverlayTrigger } from 'react-bootstrap';
+import { t } from '@superset-ui/translation';
import CopyToClipboard from './CopyToClipboard';
import { getShortUrl } from '../utils/common';
-import { t } from '../locales';
import withToasts from '../messageToasts/enhancers/withToasts';
const propTypes = {
diff --git a/superset/assets/src/components/URLShortLinkModal.jsx
b/superset/assets/src/components/URLShortLinkModal.jsx
index 907b239..1ad4d21 100644
--- a/superset/assets/src/components/URLShortLinkModal.jsx
+++ b/superset/assets/src/components/URLShortLinkModal.jsx
@@ -1,8 +1,8 @@
import React from 'react';
import PropTypes from 'prop-types';
+import { t } from '@superset-ui/translation';
import CopyToClipboard from './CopyToClipboard';
import { getShortUrl } from '../utils/common';
-import { t } from '../locales';
import withToasts from '../messageToasts/enhancers/withToasts';
import ModalTrigger from './ModalTrigger';
diff --git a/superset/assets/src/dashboard/App.jsx
b/superset/assets/src/dashboard/App.jsx
index a1d8f2e..865803b 100644
--- a/superset/assets/src/dashboard/App.jsx
+++ b/superset/assets/src/dashboard/App.jsx
@@ -6,12 +6,14 @@ import { hot } from 'react-hot-loader';
import { initFeatureFlags } from 'src/featureFlags';
import { initEnhancer } from '../reduxUtils';
-import { appSetup } from '../common';
+import setupApp from '../setup/setupApp';
+import setupPlugins from '../setup/setupPlugins';
import DashboardContainer from './containers/Dashboard';
import getInitialState from './reducers/getInitialState';
import rootReducer from './reducers/index';
-appSetup();
+setupApp();
+setupPlugins();
const appContainer = document.getElementById('app');
const bootstrapData = JSON.parse(appContainer.getAttribute('data-bootstrap'));
diff --git a/superset/assets/src/dashboard/actions/dashboardState.js
b/superset/assets/src/dashboard/actions/dashboardState.js
index 2ff139f..6fed016 100644
--- a/superset/assets/src/dashboard/actions/dashboardState.js
+++ b/superset/assets/src/dashboard/actions/dashboardState.js
@@ -1,19 +1,19 @@
/* eslint camelcase: 0 */
import { ActionCreators as UndoActionCreators } from 'redux-undo';
+import { t } from '@superset-ui/translation';
import { SupersetClient } from '@superset-ui/core';
import { addChart, removeChart, refreshChart } from '../../chart/chartAction';
import { chart as initChart } from '../../chart/chartReducer';
import { fetchDatasourceMetadata } from '../../dashboard/actions/datasources';
import { applyDefaultFormData } from '../../explore/store';
-import { getClientErrorObject } from '../../modules/utils';
+import getClientErrorObject from '../../utils/getClientErrorObject';
import {
Logger,
LOG_ACTIONS_CHANGE_DASHBOARD_FILTER,
LOG_ACTIONS_REFRESH_DASHBOARD,
} from '../../logger';
import { SAVE_TYPE_OVERWRITE } from '../util/constants';
-import { t } from '../../locales';
import {
addSuccessToast,
addWarningToast,
diff --git a/superset/assets/src/dashboard/actions/datasources.js
b/superset/assets/src/dashboard/actions/datasources.js
index 85d91bd..f5e8a48 100644
--- a/superset/assets/src/dashboard/actions/datasources.js
+++ b/superset/assets/src/dashboard/actions/datasources.js
@@ -1,5 +1,5 @@
import { SupersetClient } from '@superset-ui/core';
-import { getClientErrorObject } from '../../modules/utils';
+import getClientErrorObject from '../../utils/getClientErrorObject';
export const SET_DATASOURCE = 'SET_DATASOURCE';
export function setDatasource(datasource, key) {
diff --git a/superset/assets/src/dashboard/actions/sliceEntities.js
b/superset/assets/src/dashboard/actions/sliceEntities.js
index 31a03db..6194327 100644
--- a/superset/assets/src/dashboard/actions/sliceEntities.js
+++ b/superset/assets/src/dashboard/actions/sliceEntities.js
@@ -1,12 +1,10 @@
/* eslint camelcase: 0 */
+import { t } from '@superset-ui/translation';
import { SupersetClient } from '@superset-ui/core';
import { addDangerToast } from '../../messageToasts/actions';
-import { t } from '../../locales';
-import {
- getDatasourceParameter,
- getClientErrorObject,
-} from '../../modules/utils';
+import { getDatasourceParameter } from '../../modules/utils';
+import getClientErrorObject from '../../utils/getClientErrorObject';
export const SET_ALL_SLICES = 'SET_ALL_SLICES';
export function setAllSlices(slices) {
diff --git a/superset/assets/src/dashboard/components/AddSliceCard.jsx
b/superset/assets/src/dashboard/components/AddSliceCard.jsx
index a98546c..12f72a2 100644
--- a/superset/assets/src/dashboard/components/AddSliceCard.jsx
+++ b/superset/assets/src/dashboard/components/AddSliceCard.jsx
@@ -1,7 +1,7 @@
import cx from 'classnames';
import React from 'react';
import PropTypes from 'prop-types';
-import { t } from '../../locales';
+import { t } from '@superset-ui/translation';
const propTypes = {
datasourceLink: PropTypes.string,
diff --git a/superset/assets/src/dashboard/components/BuilderComponentPane.jsx
b/superset/assets/src/dashboard/components/BuilderComponentPane.jsx
index 4bfb2bb..145dcc3 100644
--- a/superset/assets/src/dashboard/components/BuilderComponentPane.jsx
+++ b/superset/assets/src/dashboard/components/BuilderComponentPane.jsx
@@ -4,6 +4,7 @@ import React from 'react';
import cx from 'classnames';
import { StickyContainer, Sticky } from 'react-sticky';
import { ParentSize } from '@vx/responsive';
+import { t } from '@superset-ui/translation';
import NewColumn from './gridComponents/new/NewColumn';
import NewDivider from './gridComponents/new/NewDivider';
@@ -12,7 +13,6 @@ import NewRow from './gridComponents/new/NewRow';
import NewTabs from './gridComponents/new/NewTabs';
import NewMarkdown from './gridComponents/new/NewMarkdown';
import SliceAdder from '../containers/SliceAdder';
-import { t } from '../../locales';
const SUPERSET_HEADER_HEIGHT = 59;
diff --git a/superset/assets/src/dashboard/components/CodeModal.jsx
b/superset/assets/src/dashboard/components/CodeModal.jsx
index cc0c9f2..c02f0f5 100644
--- a/superset/assets/src/dashboard/components/CodeModal.jsx
+++ b/superset/assets/src/dashboard/components/CodeModal.jsx
@@ -1,8 +1,8 @@
import React from 'react';
import PropTypes from 'prop-types';
+import { t } from '@superset-ui/translation';
import ModalTrigger from '../../components/ModalTrigger';
-import { t } from '../../locales';
const propTypes = {
triggerNode: PropTypes.node.isRequired,
diff --git a/superset/assets/src/dashboard/components/CssEditor.jsx
b/superset/assets/src/dashboard/components/CssEditor.jsx
index 45ef86d..846ee8a 100644
--- a/superset/assets/src/dashboard/components/CssEditor.jsx
+++ b/superset/assets/src/dashboard/components/CssEditor.jsx
@@ -1,13 +1,12 @@
import React from 'react';
import PropTypes from 'prop-types';
import Select from 'react-select';
-
import AceEditor from 'react-ace';
import 'brace/mode/css';
import 'brace/theme/github';
+import { t } from '@superset-ui/translation';
import ModalTrigger from '../../components/ModalTrigger';
-import { t } from '../../locales';
const propTypes = {
initialCss: PropTypes.string,
diff --git a/superset/assets/src/dashboard/components/Dashboard.jsx
b/superset/assets/src/dashboard/components/Dashboard.jsx
index 20c161b..fffcd69 100644
--- a/superset/assets/src/dashboard/components/Dashboard.jsx
+++ b/superset/assets/src/dashboard/components/Dashboard.jsx
@@ -1,5 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
+import { t } from '@superset-ui/translation';
import getChartIdsFromLayout from '../util/getChartIdsFromLayout';
import DashboardBuilder from '../containers/DashboardBuilder';
@@ -21,8 +22,6 @@ import {
LOG_ACTIONS_FIRST_DASHBOARD_LOAD,
} from '../../logger';
-import { t } from '../../locales';
-
import '../stylesheets/index.less';
const propTypes = {
diff --git a/superset/assets/src/dashboard/components/DeleteComponentModal.jsx
b/superset/assets/src/dashboard/components/DeleteComponentModal.jsx
index ea7721c..6ebdef4 100644
--- a/superset/assets/src/dashboard/components/DeleteComponentModal.jsx
+++ b/superset/assets/src/dashboard/components/DeleteComponentModal.jsx
@@ -1,9 +1,9 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Button } from 'react-bootstrap';
+import { t } from '@superset-ui/translation';
import ModalTrigger from '../../components/ModalTrigger';
-import { t } from '../../locales';
const propTypes = {
triggerNode: PropTypes.node.isRequired,
diff --git a/superset/assets/src/dashboard/components/Header.jsx
b/superset/assets/src/dashboard/components/Header.jsx
index 1dfe846..9cdafb8 100644
--- a/superset/assets/src/dashboard/components/Header.jsx
+++ b/superset/assets/src/dashboard/components/Header.jsx
@@ -1,6 +1,7 @@
/* eslint-env browser */
import React from 'react';
import PropTypes from 'prop-types';
+import { t } from '@superset-ui/translation';
import HeaderActionsDropdown from './HeaderActionsDropdown';
import EditableTitle from '../../components/EditableTitle';
@@ -9,7 +10,6 @@ import FaveStar from '../../components/FaveStar';
import UndoRedoKeylisteners from './UndoRedoKeylisteners';
import { chartPropShape } from '../util/propShapes';
-import { t } from '../../locales';
import {
UNDO_LIMIT,
SAVE_TYPE_OVERWRITE,
diff --git a/superset/assets/src/dashboard/components/HeaderActionsDropdown.jsx
b/superset/assets/src/dashboard/components/HeaderActionsDropdown.jsx
index 9967ce0..f97d4c1 100644
--- a/superset/assets/src/dashboard/components/HeaderActionsDropdown.jsx
+++ b/superset/assets/src/dashboard/components/HeaderActionsDropdown.jsx
@@ -2,13 +2,13 @@ import React from 'react';
import PropTypes from 'prop-types';
import { SupersetClient } from '@superset-ui/core';
import { DropdownButton, MenuItem } from 'react-bootstrap';
+import { t } from '@superset-ui/translation';
import CssEditor from './CssEditor';
import RefreshIntervalModal from './RefreshIntervalModal';
import SaveModal from './SaveModal';
import injectCustomCss from '../util/injectCustomCss';
import { SAVE_TYPE_NEWDASHBOARD } from '../util/constants';
-import { t } from '../../locales';
import URLShortLinkModal from '../../components/URLShortLinkModal';
import getDashboardUrl from '../util/getDashboardUrl';
diff --git a/superset/assets/src/dashboard/components/MissingChart.jsx
b/superset/assets/src/dashboard/components/MissingChart.jsx
index c45c445..56b2800 100644
--- a/superset/assets/src/dashboard/components/MissingChart.jsx
+++ b/superset/assets/src/dashboard/components/MissingChart.jsx
@@ -1,8 +1,8 @@
import PropTypes from 'prop-types';
import React from 'react';
+import { t } from '@superset-ui/translation';
import Loading from '../../components/Loading';
-import { t } from '../../locales';
const propTypes = {
height: PropTypes.number.isRequired,
diff --git a/superset/assets/src/dashboard/components/RefreshIntervalModal.jsx
b/superset/assets/src/dashboard/components/RefreshIntervalModal.jsx
index 1ed4f82..e5d375a 100644
--- a/superset/assets/src/dashboard/components/RefreshIntervalModal.jsx
+++ b/superset/assets/src/dashboard/components/RefreshIntervalModal.jsx
@@ -1,8 +1,9 @@
import React from 'react';
import PropTypes from 'prop-types';
import Select from 'react-select';
+import { t } from '@superset-ui/translation';
+
import ModalTrigger from '../../components/ModalTrigger';
-import { t } from '../../locales';
const propTypes = {
triggerNode: PropTypes.node.isRequired,
diff --git a/superset/assets/src/dashboard/components/SaveModal.jsx
b/superset/assets/src/dashboard/components/SaveModal.jsx
index 2e3d949..f726028 100644
--- a/superset/assets/src/dashboard/components/SaveModal.jsx
+++ b/superset/assets/src/dashboard/components/SaveModal.jsx
@@ -1,10 +1,10 @@
/* eslint-env browser */
import React from 'react';
import PropTypes from 'prop-types';
-
import { Button, FormControl, FormGroup, Radio } from 'react-bootstrap';
+import { t } from '@superset-ui/translation';
+
import ModalTrigger from '../../components/ModalTrigger';
-import { t } from '../../locales';
import Checkbox from '../../components/Checkbox';
import { SAVE_TYPE_OVERWRITE, SAVE_TYPE_NEWDASHBOARD } from
'../util/constants';
diff --git a/superset/assets/src/dashboard/components/SliceAdder.jsx
b/superset/assets/src/dashboard/components/SliceAdder.jsx
index 608cfc1..96b87e9 100644
--- a/superset/assets/src/dashboard/components/SliceAdder.jsx
+++ b/superset/assets/src/dashboard/components/SliceAdder.jsx
@@ -4,6 +4,7 @@ import PropTypes from 'prop-types';
import { DropdownButton, MenuItem } from 'react-bootstrap';
import { CellMeasurer, CellMeasurerCache, List } from 'react-virtualized';
import SearchInput, { createFilter } from 'react-search-input';
+import { t } from '@superset-ui/translation';
import AddSliceCard from './AddSliceCard';
import AddSliceDragPreview from './dnd/AddSliceDragPreview';
@@ -12,7 +13,6 @@ import Loading from '../../components/Loading';
import { CHART_TYPE, NEW_COMPONENT_SOURCE_TYPE } from '../util/componentTypes';
import { NEW_CHART_ID, NEW_COMPONENTS_SOURCE_ID } from '../util/constants';
import { slicePropShape } from '../util/propShapes';
-import { t } from '../../locales';
const propTypes = {
fetchAllSlices: PropTypes.func.isRequired,
diff --git a/superset/assets/src/dashboard/components/SliceHeader.jsx
b/superset/assets/src/dashboard/components/SliceHeader.jsx
index 7631ba8..325b1fc 100644
--- a/superset/assets/src/dashboard/components/SliceHeader.jsx
+++ b/superset/assets/src/dashboard/components/SliceHeader.jsx
@@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
-import { t } from '../../locales';
+import { t } from '@superset-ui/translation';
import EditableTitle from '../../components/EditableTitle';
import TooltipWrapper from '../../components/TooltipWrapper';
import SliceHeaderControls from './SliceHeaderControls';
diff --git a/superset/assets/src/dashboard/components/SliceHeaderControls.jsx
b/superset/assets/src/dashboard/components/SliceHeaderControls.jsx
index b5ee0b8..de412f1 100644
--- a/superset/assets/src/dashboard/components/SliceHeaderControls.jsx
+++ b/superset/assets/src/dashboard/components/SliceHeaderControls.jsx
@@ -2,6 +2,8 @@ import React from 'react';
import PropTypes from 'prop-types';
import moment from 'moment';
import { Dropdown, MenuItem } from 'react-bootstrap';
+import { t } from '@superset-ui/translation';
+
import {
Logger,
LOG_ACTIONS_EXPLORE_DASHBOARD_CHART,
@@ -9,8 +11,6 @@ import {
LOG_ACTIONS_REFRESH_CHART,
} from '../../logger';
-import { t } from '../../locales';
-
const propTypes = {
slice: PropTypes.object.isRequired,
isCached: PropTypes.bool,
diff --git
a/superset/assets/src/dashboard/components/gridComponents/new/NewColumn.jsx
b/superset/assets/src/dashboard/components/gridComponents/new/NewColumn.jsx
index 4698736..1c691c7 100644
--- a/superset/assets/src/dashboard/components/gridComponents/new/NewColumn.jsx
+++ b/superset/assets/src/dashboard/components/gridComponents/new/NewColumn.jsx
@@ -1,9 +1,9 @@
import React from 'react';
+import { t } from '@superset-ui/translation';
import { COLUMN_TYPE } from '../../../util/componentTypes';
import { NEW_COLUMN_ID } from '../../../util/constants';
import DraggableNewComponent from './DraggableNewComponent';
-import { t } from '../../../../locales';
export default function DraggableNewColumn() {
return (
diff --git
a/superset/assets/src/dashboard/components/gridComponents/new/NewDivider.jsx
b/superset/assets/src/dashboard/components/gridComponents/new/NewDivider.jsx
index 93518db..939ce6c 100644
--- a/superset/assets/src/dashboard/components/gridComponents/new/NewDivider.jsx
+++ b/superset/assets/src/dashboard/components/gridComponents/new/NewDivider.jsx
@@ -1,9 +1,9 @@
import React from 'react';
+import { t } from '@superset-ui/translation';
import { DIVIDER_TYPE } from '../../../util/componentTypes';
import { NEW_DIVIDER_ID } from '../../../util/constants';
import DraggableNewComponent from './DraggableNewComponent';
-import { t } from '../../../../locales';
export default function DraggableNewDivider() {
return (
diff --git
a/superset/assets/src/dashboard/components/gridComponents/new/NewHeader.jsx
b/superset/assets/src/dashboard/components/gridComponents/new/NewHeader.jsx
index 8acf853..78ac9dd 100644
--- a/superset/assets/src/dashboard/components/gridComponents/new/NewHeader.jsx
+++ b/superset/assets/src/dashboard/components/gridComponents/new/NewHeader.jsx
@@ -1,9 +1,9 @@
import React from 'react';
+import { t } from '@superset-ui/translation';
import { HEADER_TYPE } from '../../../util/componentTypes';
import { NEW_HEADER_ID } from '../../../util/constants';
import DraggableNewComponent from './DraggableNewComponent';
-import { t } from '../../../../locales';
export default function DraggableNewHeader() {
return (
diff --git
a/superset/assets/src/dashboard/components/gridComponents/new/NewRow.jsx
b/superset/assets/src/dashboard/components/gridComponents/new/NewRow.jsx
index 7a2ae01..68b0ae0 100644
--- a/superset/assets/src/dashboard/components/gridComponents/new/NewRow.jsx
+++ b/superset/assets/src/dashboard/components/gridComponents/new/NewRow.jsx
@@ -1,9 +1,9 @@
import React from 'react';
+import { t } from '@superset-ui/translation';
import { ROW_TYPE } from '../../../util/componentTypes';
import { NEW_ROW_ID } from '../../../util/constants';
import DraggableNewComponent from './DraggableNewComponent';
-import { t } from '../../../../locales';
export default function DraggableNewRow() {
return (
diff --git
a/superset/assets/src/dashboard/components/gridComponents/new/NewTabs.jsx
b/superset/assets/src/dashboard/components/gridComponents/new/NewTabs.jsx
index a77b65e..9127c94 100644
--- a/superset/assets/src/dashboard/components/gridComponents/new/NewTabs.jsx
+++ b/superset/assets/src/dashboard/components/gridComponents/new/NewTabs.jsx
@@ -1,9 +1,9 @@
import React from 'react';
+import { t } from '@superset-ui/translation';
import { TABS_TYPE } from '../../../util/componentTypes';
import { NEW_TABS_ID } from '../../../util/constants';
import DraggableNewComponent from './DraggableNewComponent';
-import { t } from '../../../../locales';
export default function DraggableNewTabs() {
return (
diff --git
a/superset/assets/src/dashboard/components/menu/MarkdownModeDropdown.jsx
b/superset/assets/src/dashboard/components/menu/MarkdownModeDropdown.jsx
index 10aa932..0be5e6f 100644
--- a/superset/assets/src/dashboard/components/menu/MarkdownModeDropdown.jsx
+++ b/superset/assets/src/dashboard/components/menu/MarkdownModeDropdown.jsx
@@ -1,6 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
-import { t } from '../../../locales';
+import { t } from '@superset-ui/translation';
import PopoverDropdown from './PopoverDropdown';
diff --git a/superset/assets/src/dashboard/reducers/sliceEntities.js
b/superset/assets/src/dashboard/reducers/sliceEntities.js
index a96368a..9f790be 100644
--- a/superset/assets/src/dashboard/reducers/sliceEntities.js
+++ b/superset/assets/src/dashboard/reducers/sliceEntities.js
@@ -1,11 +1,11 @@
+import { t } from '@superset-ui/translation';
+
import {
FETCH_ALL_SLICES_FAILED,
FETCH_ALL_SLICES_STARTED,
SET_ALL_SLICES,
} from '../actions/sliceEntities';
-import { t } from '../../locales';
-
export const initSliceEntities = {
slices: {},
isLoading: true,
diff --git a/superset/assets/src/dashboard/util/backgroundStyleOptions.js
b/superset/assets/src/dashboard/util/backgroundStyleOptions.js
index 926e7f1..885801f 100644
--- a/superset/assets/src/dashboard/util/backgroundStyleOptions.js
+++ b/superset/assets/src/dashboard/util/backgroundStyleOptions.js
@@ -1,4 +1,4 @@
-import { t } from '../../locales';
+import { t } from '@superset-ui/translation';
import { BACKGROUND_TRANSPARENT, BACKGROUND_WHITE } from './constants';
export default [
diff --git a/superset/assets/src/dashboard/util/headerStyleOptions.js
b/superset/assets/src/dashboard/util/headerStyleOptions.js
index a37bd5f..815b032 100644
--- a/superset/assets/src/dashboard/util/headerStyleOptions.js
+++ b/superset/assets/src/dashboard/util/headerStyleOptions.js
@@ -1,4 +1,4 @@
-import { t } from '../../locales';
+import { t } from '@superset-ui/translation';
import { SMALL_HEADER, MEDIUM_HEADER, LARGE_HEADER } from './constants';
export default [
diff --git a/superset/assets/src/datasource/DatasourceEditor.jsx
b/superset/assets/src/datasource/DatasourceEditor.jsx
index 7c7c8d2..98d0c9d 100644
--- a/superset/assets/src/datasource/DatasourceEditor.jsx
+++ b/superset/assets/src/datasource/DatasourceEditor.jsx
@@ -2,10 +2,9 @@ import React from 'react';
import PropTypes from 'prop-types';
import { Alert, Badge, Col, Label, Tabs, Tab, Well } from 'react-bootstrap';
import shortid from 'shortid';
+import { t } from '@superset-ui/translation';
import { SupersetClient } from '@superset-ui/core';
-import { t } from '../locales';
-
import Button from '../components/Button';
import Loading from '../components/Loading';
import CheckboxControl from '../explore/components/controls/CheckboxControl';
diff --git a/superset/assets/src/datasource/DatasourceModal.jsx
b/superset/assets/src/datasource/DatasourceModal.jsx
index 0d4d8e2..0b232d7 100644
--- a/superset/assets/src/datasource/DatasourceModal.jsx
+++ b/superset/assets/src/datasource/DatasourceModal.jsx
@@ -2,9 +2,9 @@ import React from 'react';
import PropTypes from 'prop-types';
import { Alert, Button, Modal } from 'react-bootstrap';
import Dialog from 'react-bootstrap-dialog';
+import { t } from '@superset-ui/translation';
import { SupersetClient } from '@superset-ui/core';
-import { t } from '../locales';
import DatasourceEditor from '../datasource/DatasourceEditor';
import withToasts from '../messageToasts/enhancers/withToasts';
diff --git a/superset/assets/src/explore/App.jsx
b/superset/assets/src/explore/App.jsx
index 277d34c..e14363e 100644
--- a/superset/assets/src/explore/App.jsx
+++ b/superset/assets/src/explore/App.jsx
@@ -11,11 +11,13 @@ import ExploreViewContainer from
'./components/ExploreViewContainer';
import getInitialState from './reducers/getInitialState';
import rootReducer from './reducers/index';
-import { appSetup } from '../common';
+import setupApp from '../setup/setupApp';
+import setupPlugins from '../setup/setupPlugins';
import './main.css';
import '../../stylesheets/reactable-pagination.css';
-appSetup();
+setupApp();
+setupPlugins();
const exploreViewContainer = document.getElementById('app');
const bootstrapData =
JSON.parse(exploreViewContainer.getAttribute('data-bootstrap'));
diff --git a/superset/assets/src/explore/actions/exploreActions.js
b/superset/assets/src/explore/actions/exploreActions.js
index 2323bf2..df792b2 100644
--- a/superset/assets/src/explore/actions/exploreActions.js
+++ b/superset/assets/src/explore/actions/exploreActions.js
@@ -1,7 +1,7 @@
/* eslint camelcase: 0 */
+import { t } from '@superset-ui/translation';
import { SupersetClient } from '@superset-ui/core';
import { addDangerToast } from '../../messageToasts/actions';
-import { t } from '../../locales';
const FAVESTAR_BASE_URL = '/superset/favstar/slice';
diff --git
a/superset/assets/src/explore/components/AdhocFilterEditPopoverSimpleTabContent.jsx
b/superset/assets/src/explore/components/AdhocFilterEditPopoverSimpleTabContent.jsx
index 84f8fad..5ddbe4a 100644
---
a/superset/assets/src/explore/components/AdhocFilterEditPopoverSimpleTabContent.jsx
+++
b/superset/assets/src/explore/components/AdhocFilterEditPopoverSimpleTabContent.jsx
@@ -2,12 +2,12 @@ import React from 'react';
import PropTypes from 'prop-types';
import { FormGroup } from 'react-bootstrap';
import VirtualizedSelect from 'react-virtualized-select';
+import { t } from '@superset-ui/translation';
import { SupersetClient } from '@superset-ui/core';
import AdhocFilter, { EXPRESSION_TYPES, CLAUSES } from '../AdhocFilter';
import adhocMetricType from '../propTypes/adhocMetricType';
import columnType from '../propTypes/columnType';
-import { t } from '../../locales';
import {
OPERATORS,
TABLE_ONLY_OPERATORS,
diff --git
a/superset/assets/src/explore/components/AdhocFilterEditPopoverSqlTabContent.jsx
b/superset/assets/src/explore/components/AdhocFilterEditPopoverSqlTabContent.jsx
index 6e5fe3c..e9c31d9 100644
---
a/superset/assets/src/explore/components/AdhocFilterEditPopoverSqlTabContent.jsx
+++
b/superset/assets/src/explore/components/AdhocFilterEditPopoverSqlTabContent.jsx
@@ -7,6 +7,7 @@ import 'brace/theme/github';
import 'brace/ext/language_tools';
import { FormGroup } from 'react-bootstrap';
import VirtualizedSelect from 'react-virtualized-select';
+import { t } from '@superset-ui/translation';
import { sqlWords } from '../../SqlLab/components/AceEditorWrapper';
import AdhocFilter, { EXPRESSION_TYPES, CLAUSES } from '../AdhocFilter';
@@ -14,7 +15,6 @@ import adhocMetricType from '../propTypes/adhocMetricType';
import columnType from '../propTypes/columnType';
import OnPasteSelect from '../../components/OnPasteSelect';
import VirtualizedRendererWrap from '../../components/VirtualizedRendererWrap';
-import { t } from '../../locales';
const propTypes = {
adhocFilter: PropTypes.instanceOf(AdhocFilter).isRequired,
diff --git a/superset/assets/src/explore/components/AdhocMetricEditPopover.jsx
b/superset/assets/src/explore/components/AdhocMetricEditPopover.jsx
index 96b0314..73609a0 100644
--- a/superset/assets/src/explore/components/AdhocMetricEditPopover.jsx
+++ b/superset/assets/src/explore/components/AdhocMetricEditPopover.jsx
@@ -7,9 +7,9 @@ import AceEditor from 'react-ace';
import 'brace/mode/sql';
import 'brace/theme/github';
import 'brace/ext/language_tools';
+import { t } from '@superset-ui/translation';
import { AGGREGATES } from '../constants';
-import { t } from '../../locales';
import VirtualizedRendererWrap from '../../components/VirtualizedRendererWrap';
import OnPasteSelect from '../../components/OnPasteSelect';
import AdhocMetricEditPopoverTitle from './AdhocMetricEditPopoverTitle';
diff --git a/superset/assets/src/explore/components/ControlHeader.jsx
b/superset/assets/src/explore/components/ControlHeader.jsx
index 9dcdc61..eca86c9 100644
--- a/superset/assets/src/explore/components/ControlHeader.jsx
+++ b/superset/assets/src/explore/components/ControlHeader.jsx
@@ -1,8 +1,8 @@
import React from 'react';
import PropTypes from 'prop-types';
+import { t } from '@superset-ui/translation';
import { ControlLabel, OverlayTrigger, Tooltip } from 'react-bootstrap';
import InfoTooltipWithTrigger from '../../components/InfoTooltipWithTrigger';
-import { t } from '../../locales';
const propTypes = {
name: PropTypes.string,
diff --git a/superset/assets/src/explore/components/ControlPanelsContainer.jsx
b/superset/assets/src/explore/components/ControlPanelsContainer.jsx
index fba2e57..7730a02 100644
--- a/superset/assets/src/explore/components/ControlPanelsContainer.jsx
+++ b/superset/assets/src/explore/components/ControlPanelsContainer.jsx
@@ -4,13 +4,14 @@ import PropTypes from 'prop-types';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { Alert, Tab, Tabs } from 'react-bootstrap';
+import { t } from '@superset-ui/translation';
+
import visTypes, { sectionsToRender } from '../visTypes';
import ControlPanelSection from './ControlPanelSection';
import ControlRow from './ControlRow';
import Control from './Control';
import controls from '../controls';
import * as actions from '../actions/exploreActions';
-import { t } from '../../locales';
const propTypes = {
actions: PropTypes.object.isRequired,
diff --git a/superset/assets/src/explore/components/DisplayQueryButton.jsx
b/superset/assets/src/explore/components/DisplayQueryButton.jsx
index 0029eff..de18adc 100644
--- a/superset/assets/src/explore/components/DisplayQueryButton.jsx
+++ b/superset/assets/src/explore/components/DisplayQueryButton.jsx
@@ -8,6 +8,7 @@ import jsonSyntax from
'react-syntax-highlighter/languages/hljs/json';
import github from 'react-syntax-highlighter/styles/hljs/github';
import { DropdownButton, MenuItem, Row, Col, FormControl } from
'react-bootstrap';
import { Table } from 'reactable';
+import { t } from '@superset-ui/translation';
import { SupersetClient } from '@superset-ui/core';
import CopyToClipboard from './../../components/CopyToClipboard';
@@ -16,7 +17,6 @@ import { getExploreUrlAndPayload } from '../exploreUtils';
import Loading from '../../components/Loading';
import ModalTrigger from './../../components/ModalTrigger';
import Button from '../../components/Button';
-import { t } from '../../locales';
import RowCountLabel from './RowCountLabel';
registerLanguage('markdown', markdownSyntax);
diff --git a/superset/assets/src/explore/components/EmbedCodeButton.jsx
b/superset/assets/src/explore/components/EmbedCodeButton.jsx
index e6cccac..ff28fbb 100644
--- a/superset/assets/src/explore/components/EmbedCodeButton.jsx
+++ b/superset/assets/src/explore/components/EmbedCodeButton.jsx
@@ -1,9 +1,10 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Popover, OverlayTrigger } from 'react-bootstrap';
+import { t } from '@superset-ui/translation';
+
import CopyToClipboard from './../../components/CopyToClipboard';
import { getExploreLongUrl } from '../exploreUtils';
-import { t } from '../../locales';
const propTypes = {
latestQueryFormData: PropTypes.object.isRequired,
diff --git a/superset/assets/src/explore/components/ExploreActionButtons.jsx
b/superset/assets/src/explore/components/ExploreActionButtons.jsx
index 1e60424..6bb059c 100644
--- a/superset/assets/src/explore/components/ExploreActionButtons.jsx
+++ b/superset/assets/src/explore/components/ExploreActionButtons.jsx
@@ -1,10 +1,11 @@
import React from 'react';
import PropTypes from 'prop-types';
import cx from 'classnames';
+import { t } from '@superset-ui/translation';
+
import URLShortLinkButton from '../../components/URLShortLinkButton';
import EmbedCodeButton from './EmbedCodeButton';
import DisplayQueryButton from './DisplayQueryButton';
-import { t } from '../../locales';
import { exportChart, getExploreLongUrl } from '../exploreUtils';
const propTypes = {
diff --git a/superset/assets/src/explore/components/ExploreChartHeader.jsx
b/superset/assets/src/explore/components/ExploreChartHeader.jsx
index 8c9ea91..3d6eb84 100644
--- a/superset/assets/src/explore/components/ExploreChartHeader.jsx
+++ b/superset/assets/src/explore/components/ExploreChartHeader.jsx
@@ -1,5 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
+import { t } from '@superset-ui/translation';
import { chartPropShape } from '../../dashboard/util/propShapes';
import ExploreActionButtons from './ExploreActionButtons';
@@ -10,7 +11,6 @@ import FaveStar from '../../components/FaveStar';
import TooltipWrapper from '../../components/TooltipWrapper';
import Timer from '../../components/Timer';
import CachedLabel from '../../components/CachedLabel';
-import { t } from '../../locales';
const CHART_STATUS_MAP = {
failed: 'danger',
diff --git a/superset/assets/src/explore/components/RowCountLabel.jsx
b/superset/assets/src/explore/components/RowCountLabel.jsx
index 3367d13..1ba2102 100644
--- a/superset/assets/src/explore/components/RowCountLabel.jsx
+++ b/superset/assets/src/explore/components/RowCountLabel.jsx
@@ -1,8 +1,8 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Label } from 'react-bootstrap';
+import { t } from '@superset-ui/translation';
-import { t } from '../../locales';
import { defaultNumberFormatter } from '../../modules/utils';
import TooltipWrapper from '../../components/TooltipWrapper';
diff --git a/superset/assets/src/explore/components/SaveModal.jsx
b/superset/assets/src/explore/components/SaveModal.jsx
index 5a16659..930b676 100644
--- a/superset/assets/src/explore/components/SaveModal.jsx
+++ b/superset/assets/src/explore/components/SaveModal.jsx
@@ -2,10 +2,10 @@
import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
-
import { Modal, Alert, Button, Radio } from 'react-bootstrap';
import Select from 'react-select';
-import { t } from '../../locales';
+import { t } from '@superset-ui/translation';
+
import { supersetURL } from '../../utils/common';
import { EXPLORE_ONLY_VIZ_TYPE } from '../constants';
diff --git
a/superset/assets/src/explore/components/controls/AdhocFilterControl.jsx
b/superset/assets/src/explore/components/controls/AdhocFilterControl.jsx
index b51704d..95983e5 100644
--- a/superset/assets/src/explore/components/controls/AdhocFilterControl.jsx
+++ b/superset/assets/src/explore/components/controls/AdhocFilterControl.jsx
@@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import VirtualizedSelect from 'react-virtualized-select';
-import { t } from '../../../locales';
+import { t } from '@superset-ui/translation';
import ControlHeader from '../ControlHeader';
import adhocFilterType from '../../propTypes/adhocFilterType';
import adhocMetricType from '../../propTypes/adhocMetricType';
diff --git
a/superset/assets/src/explore/components/controls/AnnotationLayer.jsx
b/superset/assets/src/explore/components/controls/AnnotationLayer.jsx
index e1c4dcf..c2e6c27 100644
--- a/superset/assets/src/explore/components/controls/AnnotationLayer.jsx
+++ b/superset/assets/src/explore/components/controls/AnnotationLayer.jsx
@@ -3,8 +3,9 @@ import PropTypes from 'prop-types';
import { CompactPicker } from 'react-color';
import { Button } from 'react-bootstrap';
import mathjs from 'mathjs';
-
+import { t } from '@superset-ui/translation';
import { SupersetClient } from '@superset-ui/core';
+
import SelectControl from './SelectControl';
import TextControl from './TextControl';
import CheckboxControl from './CheckboxControl';
@@ -21,8 +22,6 @@ import PopoverSection from
'../../../components/PopoverSection';
import ControlHeader from '../ControlHeader';
import { nonEmpty } from '../../validators';
import getChartMetadataRegistry from
'../../../visualizations/core/registries/ChartMetadataRegistrySingleton';
-
-import { t } from '../../../locales';
import getCategoricalSchemeRegistry from
'../../../modules/colors/CategoricalSchemeRegistrySingleton';
const AUTOMATIC_COLOR = '';
diff --git
a/superset/assets/src/explore/components/controls/AnnotationLayerControl.jsx
b/superset/assets/src/explore/components/controls/AnnotationLayerControl.jsx
index b33dab0..16eb4e6 100644
--- a/superset/assets/src/explore/components/controls/AnnotationLayerControl.jsx
+++ b/superset/assets/src/explore/components/controls/AnnotationLayerControl.jsx
@@ -2,14 +2,12 @@ import React from 'react';
import PropTypes from 'prop-types';
import { OverlayTrigger, Popover, ListGroup, ListGroupItem } from
'react-bootstrap';
import { connect } from 'react-redux';
+import { t } from '@superset-ui/translation';
import { getChartKey } from '../../exploreUtils';
import { runAnnotationQuery } from '../../../chart/chartAction';
import InfoTooltipWithTrigger from
'../../../components/InfoTooltipWithTrigger';
-
import AnnotationLayer from './AnnotationLayer';
-import { t } from '../../../locales';
-
const propTypes = {
colorScheme: PropTypes.string.isRequired,
diff --git a/superset/assets/src/explore/components/controls/BoundsControl.jsx
b/superset/assets/src/explore/components/controls/BoundsControl.jsx
index 803a539..d19b11b 100644
--- a/superset/assets/src/explore/components/controls/BoundsControl.jsx
+++ b/superset/assets/src/explore/components/controls/BoundsControl.jsx
@@ -1,8 +1,8 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Col, Row, FormGroup, FormControl } from 'react-bootstrap';
+import { t } from '@superset-ui/translation';
import ControlHeader from '../ControlHeader';
-import { t } from '../../../locales';
const propTypes = {
onChange: PropTypes.func,
diff --git
a/superset/assets/src/explore/components/controls/DatasourceControl.jsx
b/superset/assets/src/explore/components/controls/DatasourceControl.jsx
index cd5ad6b..271eda9 100644
--- a/superset/assets/src/explore/components/controls/DatasourceControl.jsx
+++ b/superset/assets/src/explore/components/controls/DatasourceControl.jsx
@@ -9,9 +9,9 @@ import {
Tooltip,
Well,
} from 'react-bootstrap';
+import { t } from '@superset-ui/translation';
import ControlHeader from '../ControlHeader';
-import { t } from '../../../locales';
import DatasourceModal from '../../../datasource/DatasourceModal';
import ColumnOption from '../../../components/ColumnOption';
import MetricOption from '../../../components/MetricOption';
diff --git
a/superset/assets/src/explore/components/controls/DateFilterControl.jsx
b/superset/assets/src/explore/components/controls/DateFilterControl.jsx
index c072946..366a954 100644
--- a/superset/assets/src/explore/components/controls/DateFilterControl.jsx
+++ b/superset/assets/src/explore/components/controls/DateFilterControl.jsx
@@ -18,10 +18,10 @@ import {
import Datetime from 'react-datetime';
import 'react-datetime/css/react-datetime.css';
import moment from 'moment';
+import { t } from '@superset-ui/translation';
import './DateFilterControl.css';
import ControlHeader from '../ControlHeader';
-import { t } from '../../../locales';
import PopoverSection from '../../../components/PopoverSection';
const TYPES = Object.freeze({
diff --git a/superset/assets/src/explore/components/controls/MetricsControl.jsx
b/superset/assets/src/explore/components/controls/MetricsControl.jsx
index 40f73da..7bbb4d1 100644
--- a/superset/assets/src/explore/components/controls/MetricsControl.jsx
+++ b/superset/assets/src/explore/components/controls/MetricsControl.jsx
@@ -1,8 +1,9 @@
import React from 'react';
import PropTypes from 'prop-types';
import VirtualizedSelect from 'react-virtualized-select';
+import { t } from '@superset-ui/translation';
+
import ControlHeader from '../ControlHeader';
-import { t } from '../../../locales';
import VirtualizedRendererWrap from
'../../../components/VirtualizedRendererWrap';
import OnPasteSelect from '../../../components/OnPasteSelect';
import MetricDefinitionOption from '../MetricDefinitionOption';
diff --git
a/superset/assets/src/explore/components/controls/SelectAsyncControl.jsx
b/superset/assets/src/explore/components/controls/SelectAsyncControl.jsx
index 2fb778b..b004369 100644
--- a/superset/assets/src/explore/components/controls/SelectAsyncControl.jsx
+++ b/superset/assets/src/explore/components/controls/SelectAsyncControl.jsx
@@ -1,9 +1,9 @@
import React from 'react';
import PropTypes from 'prop-types';
+import { t } from '@superset-ui/translation';
+
import Select from '../../../components/AsyncSelect';
import ControlHeader from '../ControlHeader';
-import { t } from '../../../locales';
-
import withToasts from '../../../messageToasts/enhancers/withToasts';
const propTypes = {
diff --git a/superset/assets/src/explore/components/controls/SelectControl.jsx
b/superset/assets/src/explore/components/controls/SelectControl.jsx
index 4f1e8da..9e4dc29 100644
--- a/superset/assets/src/explore/components/controls/SelectControl.jsx
+++ b/superset/assets/src/explore/components/controls/SelectControl.jsx
@@ -2,8 +2,9 @@ import React from 'react';
import PropTypes from 'prop-types';
import VirtualizedSelect from 'react-virtualized-select';
import Select, { Creatable } from 'react-select';
+import { t } from '@superset-ui/translation';
+
import ControlHeader from '../ControlHeader';
-import { t } from '../../../locales';
import VirtualizedRendererWrap from
'../../../components/VirtualizedRendererWrap';
import OnPasteSelect from '../../../components/OnPasteSelect';
diff --git a/superset/assets/src/explore/components/controls/SpatialControl.jsx
b/superset/assets/src/explore/components/controls/SpatialControl.jsx
index dac5cb9..5b9f8ac 100644
--- a/superset/assets/src/explore/components/controls/SpatialControl.jsx
+++ b/superset/assets/src/explore/components/controls/SpatialControl.jsx
@@ -3,12 +3,12 @@ import PropTypes from 'prop-types';
import {
Row, Col, Button, Label, OverlayTrigger, Popover,
} from 'react-bootstrap';
+import { t } from '@superset-ui/translation';
import ControlHeader from '../ControlHeader';
import SelectControl from './SelectControl';
import PopoverSection from '../../../components/PopoverSection';
import Checkbox from '../../../components/Checkbox';
-import { t } from '../../../locales';
const spatialTypes = {
latlong: 'latlong',
diff --git
a/superset/assets/src/explore/components/controls/TextAreaControl.jsx
b/superset/assets/src/explore/components/controls/TextAreaControl.jsx
index 4a500ea..c533804 100644
--- a/superset/assets/src/explore/components/controls/TextAreaControl.jsx
+++ b/superset/assets/src/explore/components/controls/TextAreaControl.jsx
@@ -8,12 +8,12 @@ import 'brace/mode/json';
import 'brace/mode/html';
import 'brace/mode/markdown';
import 'brace/mode/javascript';
-
import 'brace/theme/textmate';
+import { t } from '@superset-ui/translation';
+
import ControlHeader from '../ControlHeader';
import ModalTrigger from '../../../components/ModalTrigger';
-import { t } from '../../../locales';
const propTypes = {
name: PropTypes.string,
diff --git a/superset/assets/src/explore/components/controls/VizTypeControl.jsx
b/superset/assets/src/explore/components/controls/VizTypeControl.jsx
index 3fb871e..113d3c5 100644
--- a/superset/assets/src/explore/components/controls/VizTypeControl.jsx
+++ b/superset/assets/src/explore/components/controls/VizTypeControl.jsx
@@ -3,9 +3,10 @@ import PropTypes from 'prop-types';
import {
Label, Row, Col, FormControl, Modal, OverlayTrigger,
Tooltip } from 'react-bootstrap';
+import { t } from '@superset-ui/translation';
+
import visTypes from '../../visTypes';
import ControlHeader from '../ControlHeader';
-import { t } from '../../../locales';
const propTypes = {
description: PropTypes.string,
diff --git a/superset/assets/src/explore/controls.jsx
b/superset/assets/src/explore/controls.jsx
index ad32c52..92dfb1c 100644
--- a/superset/assets/src/explore/controls.jsx
+++ b/superset/assets/src/explore/controls.jsx
@@ -39,6 +39,7 @@
* each and every visualization type.
*/
import React from 'react';
+import { t } from '@superset-ui/translation';
import {
formatSelectOptionsForRange,
formatSelectOptions,
@@ -49,7 +50,6 @@ import { PRIMARY_COLOR } from '../modules/colors';
import { defaultViewport } from '../modules/geo';
import ColumnOption from '../components/ColumnOption';
import OptionDescription from '../components/OptionDescription';
-import { t } from '../locales';
import getCategoricalSchemeRegistry from
'../modules/colors/CategoricalSchemeRegistrySingleton';
import getSequentialSchemeRegistry from
'../modules/colors/SequentialSchemeRegistrySingleton';
diff --git a/superset/assets/src/explore/validators.js
b/superset/assets/src/explore/validators.js
index b1625d4..ebf4271 100644
--- a/superset/assets/src/explore/validators.js
+++ b/superset/assets/src/explore/validators.js
@@ -4,7 +4,7 @@
* as arguments and return something that evals to false if v is valid,
* and an error message if not valid.
* */
-import { t } from '../locales';
+import { t } from '@superset-ui/translation';
export function numeric(v) {
if (v && isNaN(v)) {
diff --git a/superset/assets/src/explore/visTypes.jsx
b/superset/assets/src/explore/visTypes.jsx
index 30aba88..9a0943c 100644
--- a/superset/assets/src/explore/visTypes.jsx
+++ b/superset/assets/src/explore/visTypes.jsx
@@ -3,10 +3,11 @@
* and associated with each and every visualization type.
*/
import React from 'react';
+import { t } from '@superset-ui/translation';
+
import { isFeatureEnabled, FeatureFlag } from 'src/featureFlags';
import { D3_TIME_FORMAT_OPTIONS } from './controls';
import * as v from './validators';
-import { t } from '../locales';
export const sections = {
druidTimeSeries: {
diff --git a/superset/assets/src/i18n.jsx b/superset/assets/src/i18n.jsx
deleted file mode 100644
index b27f739..0000000
--- a/superset/assets/src/i18n.jsx
+++ /dev/null
@@ -1,32 +0,0 @@
-import Jed from 'jed';
-
-const DEFAULT_LANGUAGE_PACK = {
- domain: 'superset',
- locale_data: {
- superset: {
- '': {
- domain: 'superset',
- lang: 'en',
- plural_forms: 'nplurals=1; plural=0',
- },
- },
- },
-};
-
-const i18n = (function () {
- let languagePack = DEFAULT_LANGUAGE_PACK;
-
- if (typeof window !== 'undefined') {
- const root = document.getElementById('app');
- const bootstrapData = root ?
JSON.parse(root.getAttribute('data-bootstrap')) : {};
- if (bootstrapData.common && bootstrapData.common.language_pack) {
- languagePack = bootstrapData.common.language_pack;
- delete bootstrapData.common.locale;
- delete bootstrapData.common.language_pack;
- }
- }
-
- return new Jed(languagePack);
-}());
-
-export default i18n;
diff --git a/superset/assets/src/locales.jsx b/superset/assets/src/locales.jsx
deleted file mode 100644
index 12b1a87..0000000
--- a/superset/assets/src/locales.jsx
+++ /dev/null
@@ -1,148 +0,0 @@
-/* eslint-disable global-require, import/no-dynamic-require */
-import React from 'react';
-import { sprintf } from 'sprintf-js';
-import i18n from './i18n';
-
-function formatForReact(formatString, args) {
- const rv = [];
- let cursor = 0;
- sprintf.parse(formatString).forEach((match, idx) => {
- const cpoyMatch = match;
- let copyIdx = idx;
- if (typeof match === 'string') {
- rv.push(match);
- } else {
- let arg = null;
- if (match[2]) {
- arg = args[0][match[2][0]];
- } else if (match[1]) {
- arg = args[parseInt(match[1], 10) - 1];
- } else {
- arg = args[cursor++];
- }
- if (React.isValidElement(arg)) {
- rv.push(React.cloneElement(arg, { key: idx }));
- } else {
- cpoyMatch[2] = null;
- cpoyMatch[1] = 1;
- rv.push(<span key={copyIdx++}>
- {sprintf.format([cpoyMatch], [null, arg])}
- </span>);
- }
- }
- });
- return rv;
-}
-
-function argsInvolveReact(args) {
- if (args.some(React.isValidElement)) {
- return true;
- }
- if (args.length === 1 && typeof args[0] === 'object') {
- return Object.keys(args[0]).some(function (key) {
- return React.isValidElement(args[0][key]);
- });
- }
- return false;
-}
-
-export function parseComponentTemplate(string) {
- const rv = {};
- function process(startPos, group, inGroup) {
- const regex = /\[(.*?)(:|\])|\]/g;
- let match;
- const buf = [];
- let satisfied = false;
- let pos = regex.lastIndex = startPos;
- match = regex.exec(string);
- while (match !== null) {
- const substr = string.substr(pos, match.index - pos);
- if (substr !== '') {
- buf.push(substr);
- }
- if (match[0] === ']') {
- if (inGroup) {
- satisfied = true;
- break;
- } else {
- pos = regex.lastIndex;
- continue;
- }
- }
- if (match[2] === ']') {
- pos = regex.lastIndex;
- } else {
- pos = regex.lastIndex = process(regex.lastIndex, match[1], true);
- }
- buf.push({ group: match[1] });
- match = regex.exec(string);
- }
- let endPos = regex.lastIndex;
- if (!satisfied) {
- const rest = string.substr(pos);
- if (rest) {
- buf.push(rest);
- }
- endPos = string.length;
- }
- rv[group] = buf;
- return endPos;
- }
- process(0, 'root', false);
- return rv;
-}
-
-export function renderComponentTemplate(template, components) {
- let idx = 0;
- function renderGroup(group) {
- const children = [];
- (template[group] || []).forEach((item) => {
- if (typeof item === 'string') {
- children.push(<span key={idx++}>{item}</span>);
- } else {
- children.push(renderGroup(item.group));
- }
- });
- let reference = components[group] || <span key={idx++} />;
- if (!React.isValidElement(reference)) {
- reference = <span key={idx++}>{reference}</span>;
- }
- if (children.length > 0) {
- return React.cloneElement(reference, { key: idx++ }, children);
- }
- return React.cloneElement(reference, { key: idx++ });
- }
- return renderGroup('root');
-}
-
-export function format(formatString, args) {
- if (argsInvolveReact(args)) {
- return formatForReact(formatString, args);
- }
- return sprintf(formatString, ...args);
-}
-
-export function gettext(string, ...args) {
- if (!string || !i18n) {
- return string;
- }
-
- let rv = i18n.gettext(string);
- if (args.length > 0) {
- rv = format(rv, args);
- }
- return rv;
-}
-
-export function ngettext(singular, plural, ...args) {
- return format(i18n.ngettext(singular, plural, args[0] || 0), args);
-}
-
-export function gettextComponentTemplate(template, components) {
- const tmpl = parseComponentTemplate(i18n.gettext(template));
- return renderComponentTemplate(tmpl, components);
-}
-
-export const t = gettext;
-export const tn = ngettext;
-export const tct = gettextComponentTemplate;
diff --git a/superset/assets/src/modules/utils.js
b/superset/assets/src/modules/utils.js
index 1bb656f..bc22c5a 100644
--- a/superset/assets/src/modules/utils.js
+++ b/superset/assets/src/modules/utils.js
@@ -1,10 +1,7 @@
/* eslint camelcase: 0 */
-import d3 from 'd3';
import $ from 'jquery';
-import { SupersetClient } from '@superset-ui/core';
+import d3 from 'd3';
import { formatDate, UTC } from './dates';
-import { COMMON_ERR_MESSAGES } from '../utils/common';
-import { t } from '../locales';
const siFormatter = d3.format('.3s');
@@ -109,70 +106,6 @@ export function showModal(options) {
$(options.modalSelector).modal('show');
}
-
-function showApiMessage(resp) {
- const template =
- '<div class="alert"> ' +
- '<button type="button" class="close" ' +
- 'data-dismiss="alert">\xD7</button> </div>';
- const severity = resp.severity || 'info';
- $(template).addClass('alert-' + severity)
- .append(resp.message)
- .appendTo($('#alert-container'));
-}
-
-export function getClientErrorObject(response) {
- // takes a Response object as input, attempts to read response as Json if
possible,
- // and returns a Promise that resolves to a plain object with error key and
text value.
- return new Promise((resolve) => {
- if (typeof response === 'string') {
- resolve({ error: response });
- } else if (response && response.constructor === Response &&
!response.bodyUsed) {
- // attempt to read the body as json, and fallback to text. we must clone
the
- // response in order to fallback to .text() because Response is
single-read
- response.clone().json().then((errorJson) => {
- let error = { ...response, ...errorJson };
- if (error.stack) {
- error = {
- ...error,
- error: t('Unexpected error: ') +
- (error.description || t('(no description, click to see stack
trace)')),
- stacktrace: error.stack,
- };
- } else if (error.responseText && error.responseText.indexOf('CSRF') >=
0) {
- error = {
- ...error,
- error: COMMON_ERR_MESSAGES.SESSION_TIMED_OUT,
- };
- }
- resolve(error);
- }).catch(() => {
- // fall back to reading as text
- response.text().then((errorText) => {
- resolve({ ...response, error: errorText });
- });
- });
- } else {
- // fall back to Response.statusText or generic error of we cannot read
the response
- resolve({ ...response, error: response.statusText || t('An error
occurred') });
- }
- });
-
-}
-
-export function toggleCheckbox(apiUrlPrefix, selector) {
- SupersetClient.get({ endpoint: apiUrlPrefix + $(selector)[0].checked })
- .then(() => {})
- .catch(response =>
- getClientErrorObject(response)
- .then((parsedResp) => {
- if (parsedResp && parsedResp.message) {
- showApiMessage(parsedResp);
- }
- }),
- );
-}
-
/**
* Fix the height of the table body of a DataTable with scrollY set
*/
diff --git a/superset/assets/src/preamble.js b/superset/assets/src/preamble.js
new file mode 100644
index 0000000..9d80dc9
--- /dev/null
+++ b/superset/assets/src/preamble.js
@@ -0,0 +1,24 @@
+import 'abortcontroller-polyfill/dist/abortcontroller-polyfill-only';
+import { configure } from '@superset-ui/translation';
+import setupClient from './setup/setupClient';
+import setupColors from './setup/setupColors';
+
+// Configure translation
+if (typeof window !== 'undefined') {
+ const root = document.getElementById('app');
+ const bootstrapData = root ? JSON.parse(root.getAttribute('data-bootstrap'))
: {};
+ if (bootstrapData.common && bootstrapData.common.language_pack) {
+ const languagePack = bootstrapData.common.language_pack;
+ configure({ languagePack });
+ } else {
+ configure();
+ }
+} else {
+ configure();
+}
+
+// Setup SupersetClient
+setupClient();
+
+// Setup color palettes
+setupColors();
diff --git a/superset/assets/src/profile/App.jsx
b/superset/assets/src/profile/App.jsx
index 3ad5bad..d4e175b 100644
--- a/superset/assets/src/profile/App.jsx
+++ b/superset/assets/src/profile/App.jsx
@@ -7,11 +7,11 @@ import { Provider } from 'react-redux';
import App from './components/App';
import messageToastReducer from '../messageToasts/reducers';
import { initEnhancer } from '../reduxUtils';
-import { appSetup } from '../common';
+import setupApp from '../setup/setupApp';
import './main.css';
-appSetup();
+setupApp();
const profileViewContainer = document.getElementById('app');
const bootstrap =
JSON.parse(profileViewContainer.getAttribute('data-bootstrap'));
diff --git a/superset/assets/src/profile/components/App.jsx
b/superset/assets/src/profile/components/App.jsx
index 0cb9034..c71f7b2 100644
--- a/superset/assets/src/profile/components/App.jsx
+++ b/superset/assets/src/profile/components/App.jsx
@@ -1,12 +1,13 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Col, Row, Tabs, Tab, Panel } from 'react-bootstrap';
+import { t } from '@superset-ui/translation';
+
import Favorites from './Favorites';
import UserInfo from './UserInfo';
import Security from './Security';
import RecentActivity from './RecentActivity';
import CreatedContent from './CreatedContent';
-import { t } from '../../locales';
const propTypes = {
user: PropTypes.object.isRequired,
diff --git a/superset/assets/src/profile/components/CreatedContent.jsx
b/superset/assets/src/profile/components/CreatedContent.jsx
index 00d0f9d..976162f 100644
--- a/superset/assets/src/profile/components/CreatedContent.jsx
+++ b/superset/assets/src/profile/components/CreatedContent.jsx
@@ -1,8 +1,9 @@
import React from 'react';
import PropTypes from 'prop-types';
import moment from 'moment';
+import { t } from '@superset-ui/translation';
+
import TableLoader from '../../components/TableLoader';
-import { t } from '../../locales';
const propTypes = {
user: PropTypes.object.isRequired,
diff --git a/superset/assets/src/profile/components/Favorites.jsx
b/superset/assets/src/profile/components/Favorites.jsx
index e0ef112..c6eb3e7 100644
--- a/superset/assets/src/profile/components/Favorites.jsx
+++ b/superset/assets/src/profile/components/Favorites.jsx
@@ -1,8 +1,9 @@
import React from 'react';
import PropTypes from 'prop-types';
import moment from 'moment';
+import { t } from '@superset-ui/translation';
+
import TableLoader from '../../components/TableLoader';
-import { t } from '../../locales';
const propTypes = {
user: PropTypes.object.isRequired,
diff --git a/superset/assets/src/profile/components/Security.jsx
b/superset/assets/src/profile/components/Security.jsx
index 748be6b..4783119 100644
--- a/superset/assets/src/profile/components/Security.jsx
+++ b/superset/assets/src/profile/components/Security.jsx
@@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Badge, Label } from 'react-bootstrap';
-import { t } from '../../locales';
+import { t } from '@superset-ui/translation';
const propTypes = {
user: PropTypes.object.isRequired,
diff --git a/superset/assets/src/profile/components/UserInfo.jsx
b/superset/assets/src/profile/components/UserInfo.jsx
index 4cc54be..9bd61be 100644
--- a/superset/assets/src/profile/components/UserInfo.jsx
+++ b/superset/assets/src/profile/components/UserInfo.jsx
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import Gravatar from 'react-gravatar';
import moment from 'moment';
import { Panel } from 'react-bootstrap';
-import { t } from '../../locales';
+import { t } from '@superset-ui/translation';
const propTypes = {
user: PropTypes.object.isRequired,
diff --git a/superset/assets/src/setup/setupApp.js
b/superset/assets/src/setup/setupApp.js
new file mode 100644
index 0000000..7d2fda2
--- /dev/null
+++ b/superset/assets/src/setup/setupApp.js
@@ -0,0 +1,57 @@
+/* eslint global-require: 0 */
+import $ from 'jquery';
+import { SupersetClient } from '@superset-ui/core';
+import getClientErrorObject from '../utils/getClientErrorObject';
+
+function showApiMessage(resp) {
+ const template =
+ '<div class="alert"> ' +
+ '<button type="button" class="close" ' +
+ 'data-dismiss="alert">\xD7</button> </div>';
+ const severity = resp.severity || 'info';
+ $(template).addClass('alert-' + severity)
+ .append(resp.message)
+ .appendTo($('#alert-container'));
+}
+
+function toggleCheckbox(apiUrlPrefix, selector) {
+ SupersetClient.get({ endpoint: apiUrlPrefix + $(selector)[0].checked })
+ .then(() => {})
+ .catch(response =>
+ getClientErrorObject(response)
+ .then((parsedResp) => {
+ if (parsedResp && parsedResp.message) {
+ showApiMessage(parsedResp);
+ }
+ }),
+ );
+}
+
+export default function setupApp() {
+ $(document).ready(function () {
+ $(':checkbox[data-checkbox-api-prefix]').change(function () {
+ const $this = $(this);
+ const prefix = $this.data('checkbox-api-prefix');
+ const id = $this.attr('id');
+ toggleCheckbox(prefix, '#' + id);
+ });
+
+ // for language picker dropdown
+ $('#language-picker a').click(function (ev) {
+ ev.preventDefault();
+ SupersetClient.get({
+ endpoint: ev.currentTarget.getAttribute('href'),
+ parseMethod: null,
+ })
+ .then(() => {
+ location.reload();
+ });
+ });
+ });
+
+ // A set of hacks to allow apps to run within a FAB template
+ // this allows for the server side generated menus to function
+ window.$ = $;
+ window.jQuery = $;
+ require('bootstrap');
+}
diff --git a/superset/assets/src/utils/common.js
b/superset/assets/src/utils/common.js
index 9fbe35b..a22ca9a 100644
--- a/superset/assets/src/utils/common.js
+++ b/superset/assets/src/utils/common.js
@@ -1,8 +1,5 @@
-/* eslint global-require: 0 */
+import d3 from 'd3';
import { SupersetClient } from '@superset-ui/core';
-import { t } from '../locales';
-
-const d3 = require('d3');
export const EARTH_CIRCUMFERENCE_KM = 40075.16;
export const LUMINANCE_RED_WEIGHT = 0.2126;
@@ -113,10 +110,5 @@ export function optionFromValue(opt) {
return { value: optionValue(opt), label: optionLabel(opt) };
}
-// Error messages used in many places across applications
-export const COMMON_ERR_MESSAGES = {
- SESSION_TIMED_OUT: t('Your session timed out, please refresh your page and
try again.'),
-};
-
// time_range separator
export const TIME_RANGE_SEPARATOR = ' : ';
diff --git a/superset/assets/src/utils/errorMessages.js
b/superset/assets/src/utils/errorMessages.js
new file mode 100644
index 0000000..70117b2
--- /dev/null
+++ b/superset/assets/src/utils/errorMessages.js
@@ -0,0 +1,6 @@
+// Error messages used in many places across applications
+const COMMON_ERR_MESSAGES = {
+ SESSION_TIMED_OUT: 'Your session timed out, please refresh your page and try
again.',
+};
+
+export default COMMON_ERR_MESSAGES;
diff --git a/superset/assets/src/utils/getClientErrorObject.js
b/superset/assets/src/utils/getClientErrorObject.js
new file mode 100644
index 0000000..ea0ea44
--- /dev/null
+++ b/superset/assets/src/utils/getClientErrorObject.js
@@ -0,0 +1,40 @@
+import { t } from '@superset-ui/translation';
+import COMMON_ERR_MESSAGES from './errorMessages';
+
+export default function getClientErrorObject(response) {
+ // takes a Response object as input, attempts to read response as Json if
possible,
+ // and returns a Promise that resolves to a plain object with error key and
text value.
+ return new Promise((resolve) => {
+ if (typeof response === 'string') {
+ resolve({ error: response });
+ } else if (response && response.constructor === Response &&
!response.bodyUsed) {
+ // attempt to read the body as json, and fallback to text. we must clone
the
+ // response in order to fallback to .text() because Response is
single-read
+ response.clone().json().then((errorJson) => {
+ let error = { ...response, ...errorJson };
+ if (error.stack) {
+ error = {
+ ...error,
+ error: t('Unexpected error: ') +
+ (error.description || t('(no description, click to see stack
trace)')),
+ stacktrace: error.stack,
+ };
+ } else if (error.responseText && error.responseText.indexOf('CSRF') >=
0) {
+ error = {
+ ...error,
+ error: t(COMMON_ERR_MESSAGES.SESSION_TIMED_OUT),
+ };
+ }
+ resolve(error);
+ }).catch(() => {
+ // fall back to reading as text
+ response.text().then((errorText) => {
+ resolve({ ...response, error: errorText });
+ });
+ });
+ } else {
+ // fall back to Response.statusText or generic error of we cannot read
the response
+ resolve({ ...response, error: response.statusText || t('An error
occurred') });
+ }
+ });
+}
diff --git a/superset/assets/src/visualizations/EventFlow/EventFlow.jsx
b/superset/assets/src/visualizations/EventFlow/EventFlow.jsx
index 7359bda..4a688e6 100644
--- a/superset/assets/src/visualizations/EventFlow/EventFlow.jsx
+++ b/superset/assets/src/visualizations/EventFlow/EventFlow.jsx
@@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { App, withParentSize } from '@data-ui/event-flow';
-import { t } from '../../locales';
+import { t } from '@superset-ui/translation';
const propTypes = {
className: PropTypes.string,
diff --git a/superset/assets/src/visualizations/FilterBox/FilterBox.jsx
b/superset/assets/src/visualizations/FilterBox/FilterBox.jsx
index 907e802..05b9c9f 100644
--- a/superset/assets/src/visualizations/FilterBox/FilterBox.jsx
+++ b/superset/assets/src/visualizations/FilterBox/FilterBox.jsx
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
import VirtualizedSelect from 'react-virtualized-select';
import { Creatable } from 'react-select';
import { Button } from 'react-bootstrap';
+import { t } from '@superset-ui/translation';
import DateFilterControl from
'../../explore/components/controls/DateFilterControl';
import ControlRow from '../../explore/components/ControlRow';
@@ -10,7 +11,6 @@ import Control from '../../explore/components/Control';
import controls from '../../explore/controls';
import OnPasteSelect from '../../components/OnPasteSelect';
import VirtualizedRendererWrap from '../../components/VirtualizedRendererWrap';
-import { t } from '../../locales';
import './FilterBox.css';
// maps control names to their key in extra_filters
diff --git a/superset/assets/src/visualizations/PlaySlider.jsx
b/superset/assets/src/visualizations/PlaySlider.jsx
index 88b0335..891c848 100644
--- a/superset/assets/src/visualizations/PlaySlider.jsx
+++ b/superset/assets/src/visualizations/PlaySlider.jsx
@@ -1,14 +1,11 @@
import React from 'react';
import PropTypes from 'prop-types';
-import { Row, Col } from 'react-bootstrap';
-
import Mousetrap from 'mousetrap';
-
+import { Row, Col } from 'react-bootstrap';
+import { t } from '@superset-ui/translation';
import BootrapSliderWrapper from '../components/BootstrapSliderWrapper';
import './PlaySlider.css';
-import { t } from '../locales';
-
const propTypes = {
start: PropTypes.number.isRequired,
step: PropTypes.number.isRequired,
diff --git a/superset/assets/src/visualizations/nvd3/NVD3Vis.js
b/superset/assets/src/visualizations/nvd3/NVD3Vis.js
index a67c93f..1267b42 100644
--- a/superset/assets/src/visualizations/nvd3/NVD3Vis.js
+++ b/superset/assets/src/visualizations/nvd3/NVD3Vis.js
@@ -4,9 +4,9 @@ import nv from 'nvd3';
import mathjs from 'mathjs';
import moment from 'moment';
import PropTypes from 'prop-types';
+import { t } from '@superset-ui/translation';
import 'nvd3/build/nv.d3.min.css';
-import { t } from '../../locales';
import ANNOTATION_TYPES, { applyNativeColumns } from
'../../modules/AnnotationTypes';
import { getScale, getColor } from
'../../modules/colors/CategoricalColorNamespace';
import { formatDateVerbose } from '../../modules/dates';
diff --git a/superset/assets/src/welcome/App.jsx
b/superset/assets/src/welcome/App.jsx
index b22c162..4a894ca 100644
--- a/superset/assets/src/welcome/App.jsx
+++ b/superset/assets/src/welcome/App.jsx
@@ -6,11 +6,10 @@ import { Provider } from 'react-redux';
import messageToastReducer from '../messageToasts/reducers';
import { initEnhancer } from '../reduxUtils';
-
-import { appSetup } from '../common';
+import setupApp from '../setup/setupApp';
import Welcome from './Welcome';
-appSetup();
+setupApp();
const container = document.getElementById('app');
const bootstrap = JSON.parse(container.getAttribute('data-bootstrap'));
diff --git a/superset/assets/src/welcome/DashboardTable.jsx
b/superset/assets/src/welcome/DashboardTable.jsx
index 29c2988..c03e34c 100644
--- a/superset/assets/src/welcome/DashboardTable.jsx
+++ b/superset/assets/src/welcome/DashboardTable.jsx
@@ -2,9 +2,9 @@ import React from 'react';
import PropTypes from 'prop-types';
import { Table, Tr, Td, unsafe } from 'reactable';
import { SupersetClient } from '@superset-ui/core';
-import withToasts from '../messageToasts/enhancers/withToasts';
-import { t } from '../locales';
+import { t } from '@superset-ui/translation';
+import withToasts from '../messageToasts/enhancers/withToasts';
import Loading from '../components/Loading';
import '../../stylesheets/reactable-pagination.css';
diff --git a/superset/assets/src/welcome/Welcome.jsx
b/superset/assets/src/welcome/Welcome.jsx
index 2f4de97..d059ee1 100644
--- a/superset/assets/src/welcome/Welcome.jsx
+++ b/superset/assets/src/welcome/Welcome.jsx
@@ -1,10 +1,10 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Panel, Row, Col, Tabs, Tab, FormControl } from 'react-bootstrap';
+import { t } from '@superset-ui/translation';
import RecentActivity from '../profile/components/RecentActivity';
import Favorites from '../profile/components/Favorites';
import DashboardTable from './DashboardTable';
-import { t } from '../locales';
const propTypes = {
user: PropTypes.object.isRequired,
diff --git a/superset/assets/webpack.config.js
b/superset/assets/webpack.config.js
index 9da6528..c37ad55 100644
--- a/superset/assets/webpack.config.js
+++ b/superset/assets/webpack.config.js
@@ -79,19 +79,28 @@ if (isDevMode) {
output.chunkFilename = '[name].[chunkhash].chunk.js';
}
+const PREAMBLE = [
+ 'babel-polyfill',
+ path.join(APP_DIR, '/src/preamble.js'),
+];
+
+function addPreamble(entry) {
+ return PREAMBLE.concat([path.join(APP_DIR, entry)]);
+}
+
const config = {
node: {
fs: 'empty',
},
entry: {
- theme: APP_DIR + '/src/theme.js',
- common: APP_DIR + '/src/common.js',
- addSlice: ['babel-polyfill', APP_DIR + '/src/addSlice/index.jsx'],
- explore: ['babel-polyfill', APP_DIR + '/src/explore/index.jsx'],
- dashboard: ['babel-polyfill', APP_DIR + '/src/dashboard/index.jsx'],
- sqllab: ['babel-polyfill', APP_DIR + '/src/SqlLab/index.jsx'],
- welcome: ['babel-polyfill', APP_DIR + '/src/welcome/index.jsx'],
- profile: ['babel-polyfill', APP_DIR + '/src/profile/index.jsx'],
+ theme: path.join(APP_DIR, '/src/theme.js'),
+ preamble: PREAMBLE,
+ addSlice: addPreamble('/src/addSlice/index.jsx'),
+ explore: addPreamble('/src/explore/index.jsx'),
+ dashboard: addPreamble('/src/dashboard/index.jsx'),
+ sqllab: addPreamble('/src/SqlLab/index.jsx'),
+ welcome: addPreamble('/src/welcome/index.jsx'),
+ profile: addPreamble('/src/profile/index.jsx'),
},
output,
optimization: {
@@ -103,7 +112,7 @@ const config = {
default: false,
major: {
name: 'vendors-major',
- test: /[\\/]node_modules\/(brace|react[-]dom|core[-]js)[\\/]/,
+ test:
/[\\/]node_modules\/(brace|react[-]dom|core[-]js|@superset[-]ui\/translation)[\\/]/,
},
},
},
diff --git a/superset/assets/yarn.lock b/superset/assets/yarn.lock
index a6ffc95..a59ef5e 100644
--- a/superset/assets/yarn.lock
+++ b/superset/assets/yarn.lock
@@ -406,6 +406,13 @@
"@babel/runtime" "^7.1.2"
whatwg-fetch "^2.0.4"
+"@superset-ui/translation@^0.2.1":
+ version "0.2.1"
+ resolved
"https://registry.yarnpkg.com/@superset-ui/translation/-/translation-0.2.1.tgz#252025d566918782bafc25cb9fe2aa31f9917093"
+ dependencies:
+ "@babel/runtime" "^7.1.2"
+ jed "^1.1.1"
+
"@types/[email protected]":
version "1.3.3"
resolved
"https://registry.yarnpkg.com/@types/blob-util/-/blob-util-1.3.3.tgz#adba644ae34f88e1dd9a5864c66ad651caaf628a"
@@ -2697,7 +2704,7 @@ class-utils@^0.3.5:
isobject "^3.0.0"
static-extend "^0.1.1"
-classnames@^2.1.2, classnames@^2.2.3, classnames@^2.2.4, classnames@^2.2.5:
+classnames@^2.2.3, classnames@^2.2.4, classnames@^2.2.5:
version "2.2.6"
resolved
"https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce"
@@ -4452,10 +4459,6 @@ [email protected]:
dependencies:
pify "^2.2.0"
-exenv@^1.2.0:
- version "1.2.2"
- resolved
"https://registry.yarnpkg.com/exenv/-/exenv-1.2.2.tgz#2ae78e85d9894158670b03d47bec1f03bd91bb9d"
-
exif-parser@^0.1.9:
version "0.1.12"
resolved
"https://registry.yarnpkg.com/exif-parser/-/exif-parser-0.1.12.tgz#58a9d2d72c02c1f6f02a0ef4a9166272b7760922"
@@ -9350,15 +9353,6 @@ [email protected]:
bootstrap-slider "9.9.0"
es6bindall "^0.0.9"
-react-bootstrap-table@^4.3.1:
- version "4.3.1"
- resolved
"https://registry.yarnpkg.com/react-bootstrap-table/-/react-bootstrap-table-4.3.1.tgz#f704be55b7f6bf0557d2fc5bec6d25fd307d0cde"
- dependencies:
- classnames "^2.1.2"
- prop-types "^15.5.10"
- react-modal "^3.1.7"
- react-s-alert "^1.3.2"
-
react-bootstrap@^0.31.5:
version "0.31.5"
resolved
"https://registry.yarnpkg.com/react-bootstrap/-/react-bootstrap-0.31.5.tgz#57040fa8b1274e1e074803c21a1b895fdabea05a"
@@ -9455,7 +9449,7 @@ react-is@^16.3.2, react-is@^16.5.2:
version "16.5.2"
resolved
"https://registry.yarnpkg.com/react-is/-/react-is-16.5.2.tgz#e2a7b7c3f5d48062eb769fcb123505eb928722e3"
-react-lifecycles-compat@^3.0.0, react-lifecycles-compat@^3.0.4:
+react-lifecycles-compat@^3.0.4:
version "3.0.4"
resolved
"https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
@@ -9488,15 +9482,6 @@ react-markdown@^3.3.0:
unist-util-visit "^1.3.0"
xtend "^4.0.1"
-react-modal@^3.1.7:
- version "3.6.1"
- resolved
"https://registry.yarnpkg.com/react-modal/-/react-modal-3.6.1.tgz#54d27a1ec2b493bbc451c7efaa3557b6af82332d"
- dependencies:
- exenv "^1.2.0"
- prop-types "^15.5.10"
- react-lifecycles-compat "^3.0.0"
- warning "^3.0.0"
-
react-move@^2.1.0:
version "2.8.0"
resolved
"https://registry.yarnpkg.com/react-move/-/react-move-2.8.0.tgz#63deaf6a0e58ca6769357abfcd91dde44d83a596"
@@ -9536,12 +9521,6 @@ react-resizable@^1.3.3:
prop-types "15.x"
react-draggable "^2.2.6 || ^3.0.3"
-react-s-alert@^1.3.2:
- version "1.4.1"
- resolved
"https://registry.yarnpkg.com/react-s-alert/-/react-s-alert-1.4.1.tgz#ef3665a9d98c4cf2e448fc2d84e48aeca799bb5a"
- dependencies:
- babel-runtime "^6.23.0"
-
react-search-input@^0.11.3:
version "0.11.3"
resolved
"https://registry.yarnpkg.com/react-search-input/-/react-search-input-0.11.3.tgz#3dd1f9fc584b6bc40a6ee133ae042b6fbb7ae8dd"
@@ -10823,10 +10802,6 @@ split@~0.2.10:
dependencies:
through "2"
-sprintf-js@^1.1.1:
- version "1.1.1"
- resolved
"https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.1.tgz#36be78320afe5801f6cea3ee78b6e5aab940ea0c"
-
sprintf-js@~1.0.2:
version "1.0.3"
resolved
"https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
diff --git a/superset/templates/superset/base.html
b/superset/templates/superset/base.html
index b4397f5..b2dba50 100644
--- a/superset/templates/superset/base.html
+++ b/superset/templates/superset/base.html
@@ -10,14 +10,14 @@
{% block head_js %}
{{super()}}
- {% for entry in get_unloaded_chunks(js_manifest('theme'), loaded_chunks) %}
- <script src="{{ entry }}"></script>
- {% endfor %}
+ {% with filename="theme" %}
+ {% include "superset/partials/_script_tag.html" %}
+ {% endwith %}
{% endblock %}
{% block tail_js %}
{{super()}}
- {% for entry in get_unloaded_chunks(js_manifest('common'), loaded_chunks)
%}
- <script src="{{ entry }}"></script>
- {% endfor %}
+ {% with filename="preamble" %}
+ {% include "superset/partials/_script_tag.html" %}
+ {% endwith %}
{% endblock %}
diff --git a/superset/templates/superset/basic.html
b/superset/templates/superset/basic.html
index a5e72f3..f096b55 100644
--- a/superset/templates/superset/basic.html
+++ b/superset/templates/superset/basic.html
@@ -29,12 +29,9 @@
{% endblock %}
- {% for entry in get_unloaded_chunks(js_manifest('theme'), loaded_chunks) %}
- <script src="{{ entry }}"></script>
- {% endfor %}
- {% for entry in get_unloaded_chunks(js_manifest('common'), loaded_chunks)
%}
- <script src="{{ entry }}"></script>
- {% endfor %}
+ {% with filename="theme" %}
+ {% include "superset/partials/_script_tag.html" %}
+ {% endwith %}
<input
type="hidden"
@@ -79,10 +76,9 @@
</div>
{% block tail_js %}
{% if entry %}
- {% set entry_files = js_manifest(entry) %}
- {% for entry in get_unloaded_chunks(entry_files, loaded_chunks) %}
- <script src="{{ entry }}"></script>
- {% endfor %}
+ {% with filename=entry %}
+ {% include "superset/partials/_script_tag.html" %}
+ {% endwith %}
{% endif %}
{% endblock %}
</body>
diff --git a/superset/templates/superset/partials/_script_tag.html
b/superset/templates/superset/partials/_script_tag.html
index f530c7b..1677925 100644
--- a/superset/templates/superset/partials/_script_tag.html
+++ b/superset/templates/superset/partials/_script_tag.html
@@ -1,4 +1,4 @@
-{% block tail_js %}
+{% block partial_js %}
{% for entry in get_unloaded_chunks(js_manifest(filename), loaded_chunks) %}
<script src="{{ entry }}"></script>
{% endfor %}