diff --git a/superset-frontend/src/explore/components/controls/DateFilterControl/components/CustomFrame.test.tsx b/superset-frontend/src/explore/components/controls/DateFilterControl/components/CustomFrame.test.tsx
index 6cb5c4f56cd0f..aa7da5fedfb57 100644
--- a/superset-frontend/src/explore/components/controls/DateFilterControl/components/CustomFrame.test.tsx
+++ b/superset-frontend/src/explore/components/controls/DateFilterControl/components/CustomFrame.test.tsx
@@ -17,6 +17,9 @@
* under the License.
*/
import React from 'react';
+import thunk from 'redux-thunk';
+import { Provider } from 'react-redux';
+import configureStore from 'redux-mock-store';
import { render, screen } from 'spec/helpers/testing-library';
import userEvent from '@testing-library/user-event';
import { CustomFrame } from '.';
@@ -29,8 +32,17 @@ const specificValue = '2021-03-16T00:00:00 : 2021-03-17T00:00:00';
const relativeNowValue = `DATEADD(DATETIME("now"), -7, day) : DATEADD(DATETIME("now"), 7, day)`;
const relativeTodayValue = `DATEADD(DATETIME("today"), -7, day) : DATEADD(DATETIME("today"), 7, day)`;
+const mockStore = configureStore([thunk]);
+const store = mockStore({
+ common: { locale: 'en' },
+});
+
test('renders with default props', () => {
- render();
+ render(
+
+
+ ,
+ );
expect(screen.getByText('Configure custom time range')).toBeInTheDocument();
expect(screen.getByText('Relative Date/Time')).toBeInTheDocument();
expect(screen.getByRole('spinbutton')).toBeInTheDocument();
@@ -40,13 +52,21 @@ test('renders with default props', () => {
});
test('renders since and until with specific date/time', () => {
- render();
+ render(
+
+
+ ,
+ );
expect(screen.getAllByText('Specific Date/Time').length).toBe(2);
expect(screen.getAllByRole('img', { name: 'calendar' }).length).toBe(2);
});
test('renders since and until with relative date/time', () => {
- render();
+ render(
+
+
+ ,
+ );
expect(screen.getAllByText('Relative Date/Time').length).toBe(2);
expect(screen.getAllByRole('spinbutton').length).toBe(2);
expect(screen.getByText('Days Before')).toBeInTheDocument();
@@ -54,17 +74,29 @@ test('renders since and until with relative date/time', () => {
});
test('renders since and until with Now option', () => {
- render();
+ render(
+
+
+ ,
+ );
expect(screen.getAllByText('Now').length).toBe(2);
});
test('renders since and until with Midnight option', () => {
- render();
+ render(
+
+
+ ,
+ );
expect(screen.getAllByText('Midnight').length).toBe(2);
});
test('renders anchor with now option', () => {
- render();
+ render(
+
+
+ ,
+ );
expect(screen.getByText('Anchor to')).toBeInTheDocument();
expect(screen.getByRole('radio', { name: 'NOW' })).toBeInTheDocument();
expect(screen.getByRole('radio', { name: 'Date/Time' })).toBeInTheDocument();
@@ -72,7 +104,11 @@ test('renders anchor with now option', () => {
});
test('renders anchor with date/time option', () => {
- render();
+ render(
+
+
+ ,
+ );
expect(screen.getByText('Anchor to')).toBeInTheDocument();
expect(screen.getByRole('radio', { name: 'NOW' })).toBeInTheDocument();
expect(screen.getByRole('radio', { name: 'Date/Time' })).toBeInTheDocument();
@@ -81,21 +117,33 @@ test('renders anchor with date/time option', () => {
test('triggers onChange when the anchor changes', () => {
const onChange = jest.fn();
- render();
+ render(
+
+
+ ,
+ );
userEvent.click(screen.getByRole('radio', { name: 'Date/Time' }));
expect(onChange).toHaveBeenCalled();
});
test('triggers onChange when the value changes', () => {
const onChange = jest.fn();
- render();
+ render(
+
+
+ ,
+ );
userEvent.click(screen.getByRole('img', { name: 'up' }));
expect(onChange).toHaveBeenCalled();
});
test('triggers onChange when the mode changes', () => {
const onChange = jest.fn();
- render();
+ render(
+
+
+ ,
+ );
userEvent.click(screen.getByTitle('Midnight'));
userEvent.click(screen.getByTitle('Relative Date/Time'));
userEvent.click(screen.getAllByTitle('Now')[1]);
@@ -105,7 +153,11 @@ test('triggers onChange when the mode changes', () => {
test('triggers onChange when the grain changes', async () => {
const onChange = jest.fn();
- render();
+ render(
+
+
+ ,
+ );
userEvent.click(screen.getByText('Days Before'));
userEvent.click(screen.getByText('Weeks Before'));
userEvent.click(screen.getByText('Days After'));
@@ -115,7 +167,11 @@ test('triggers onChange when the grain changes', async () => {
test('triggers onChange when the date changes', async () => {
const onChange = jest.fn();
- render();
+ render(
+
+
+ ,
+ );
const inputs = screen.getAllByPlaceholderText('Select date');
userEvent.click(inputs[0]);
userEvent.click(screen.getAllByText('Now')[0]);
@@ -123,3 +179,24 @@ test('triggers onChange when the date changes', async () => {
userEvent.click(screen.getAllByText('Now')[1]);
expect(onChange).toHaveBeenCalledTimes(2);
});
+
+test('should translate Date Picker', () => {
+ const onChange = jest.fn();
+ const store = mockStore({
+ common: { locale: 'fr' },
+ });
+ render(
+
+
+ ,
+ );
+ userEvent.click(screen.getAllByRole('img', { name: 'calendar' })[0]);
+ expect(screen.getByText('2021')).toBeInTheDocument();
+ expect(screen.getByText('lu')).toBeInTheDocument();
+ expect(screen.getByText('ma')).toBeInTheDocument();
+ expect(screen.getByText('me')).toBeInTheDocument();
+ expect(screen.getByText('je')).toBeInTheDocument();
+ expect(screen.getByText('ve')).toBeInTheDocument();
+ expect(screen.getByText('sa')).toBeInTheDocument();
+ expect(screen.getByText('di')).toBeInTheDocument();
+});
diff --git a/superset-frontend/src/explore/components/controls/DateFilterControl/components/CustomFrame.tsx b/superset-frontend/src/explore/components/controls/DateFilterControl/components/CustomFrame.tsx
index 48637f36e33f7..7f22125945cac 100644
--- a/superset-frontend/src/explore/components/controls/DateFilterControl/components/CustomFrame.tsx
+++ b/superset-frontend/src/explore/components/controls/DateFilterControl/components/CustomFrame.tsx
@@ -17,9 +17,12 @@
* under the License.
*/
import React from 'react';
+import { useSelector } from 'react-redux';
import { t } from '@superset-ui/core';
import { Moment } from 'moment';
import { isInteger } from 'lodash';
+// @ts-ignore
+import { locales } from 'antd/dist/antd-with-locales';
import { Col, Row } from 'src/components';
import { InputNumber } from 'src/components/Input';
import { DatePicker } from 'src/components/DatePicker';
@@ -36,11 +39,13 @@ import {
customTimeRangeDecode,
customTimeRangeEncode,
dttmToMoment,
+ LOCALE_MAPPING,
} from 'src/explore/components/controls/DateFilterControl/utils';
import {
CustomRangeKey,
FrameComponentProps,
} from 'src/explore/components/controls/DateFilterControl/types';
+import { ExplorePageState } from 'src/explore/types';
export function CustomFrame(props: FrameComponentProps) {
const { customRange, matchedFlag } = customTimeRangeDecode(props.value);
@@ -105,6 +110,10 @@ export function CustomFrame(props: FrameComponentProps) {
}
}
+ const localFromFlaskBabel =
+ useSelector((state: ExplorePageState) => state.common.locale) || 'en';
+ const currentLocale = locales[LOCALE_MAPPING[localFromFlaskBabel]].DatePicker;
+
return (
{t('Configure custom time range')}
@@ -132,6 +141,7 @@ export function CustomFrame(props: FrameComponentProps) {
onChange('sinceDatetime', datetime.format(MOMENT_FORMAT))
}
allowClear={false}
+ locale={currentLocale}
/>
)}
@@ -184,6 +194,7 @@ export function CustomFrame(props: FrameComponentProps) {
onChange('untilDatetime', datetime.format(MOMENT_FORMAT))
}
allowClear={false}
+ locale={currentLocale}
/>
)}
@@ -241,6 +252,7 @@ export function CustomFrame(props: FrameComponentProps) {
}
allowClear={false}
className="control-anchor-to-datetime"
+ locale={currentLocale}
/>
)}
diff --git a/superset-frontend/src/explore/components/controls/DateFilterControl/utils/constants.ts b/superset-frontend/src/explore/components/controls/DateFilterControl/utils/constants.ts
index 99dac1bdbe313..ca4a1f344d8dd 100644
--- a/superset-frontend/src/explore/components/controls/DateFilterControl/utils/constants.ts
+++ b/superset-frontend/src/explore/components/controls/DateFilterControl/utils/constants.ts
@@ -114,3 +114,20 @@ export const SEVEN_DAYS_AGO = moment()
.subtract(7, 'days')
.format(MOMENT_FORMAT);
export const MIDNIGHT = moment().utc().startOf('day').format(MOMENT_FORMAT);
+
+export const LOCALE_MAPPING = {
+ en: 'en_US',
+ fr: 'fr_FR',
+ es: 'es_ES',
+ it: 'it_IT',
+ zh: 'zh_CN',
+ ja: 'ja_JP',
+ de: 'de_DE',
+ pt: 'pt_PT',
+ pt_BR: 'pt_BR',
+ ru: 'ru_RU',
+ ko: 'ko_KR',
+ sk: 'sk_SK',
+ sl: 'sl_SI',
+ nl: 'nl_NL',
+};