diff --git a/superset-frontend/src/components/ListView/Filters/DateRange.tsx b/superset-frontend/src/components/ListView/Filters/DateRange.tsx
index b7816dcdb8ec9..bf03012eedf4a 100644
--- a/superset-frontend/src/components/ListView/Filters/DateRange.tsx
+++ b/superset-frontend/src/components/ListView/Filters/DateRange.tsx
@@ -29,6 +29,9 @@ import { RangePicker } from 'src/components/DatePicker';
import { FormLabel } from 'src/components/Form';
import { extendedDayjs } from 'src/utils/dates';
import { Dayjs } from 'dayjs';
+import Loading from 'src/components/Loading';
+import { AntdThemeProvider } from 'src/components/AntdThemeProvider';
+import { useLocale } from 'src/hooks/useLocale';
import { BaseFilter, FilterHandler } from './Base';
interface DateRangeFilterProps extends BaseFilter {
@@ -56,6 +59,8 @@ function DateRangeFilter(
return [extendedDayjs(value[0]), extendedDayjs(value[1])];
}, [value]);
+ const locale = useLocale();
+
useImperativeHandle(ref, () => ({
clearFilter: () => {
setValue(null);
@@ -63,28 +68,33 @@ function DateRangeFilter(
},
}));
+ if (locale === null) {
+ return ;
+ }
return (
-
- {Header}
- {
- if (!dayjsRange?.[0]?.valueOf() || !dayjsRange?.[1]?.valueOf()) {
- setValue(null);
- onSubmit([]);
- return;
- }
- const changeValue = [
- dayjsRange[0]?.valueOf() ?? 0,
- dayjsRange[1]?.valueOf() ?? 0,
- ] as ValueState;
- setValue(changeValue);
- onSubmit(changeValue);
- }}
- />
-
+
+
+ {Header}
+ {
+ if (!dayjsRange?.[0]?.valueOf() || !dayjsRange?.[1]?.valueOf()) {
+ setValue(null);
+ onSubmit([]);
+ return;
+ }
+ const changeValue = [
+ dayjsRange[0]?.valueOf() ?? 0,
+ dayjsRange[1]?.valueOf() ?? 0,
+ ] as ValueState;
+ setValue(changeValue);
+ onSubmit(changeValue);
+ }}
+ />
+
+
);
}
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 4ac8cfc4e0d6e..ec558c0909890 100644
--- a/superset-frontend/src/explore/components/controls/DateFilterControl/components/CustomFrame.tsx
+++ b/superset-frontend/src/explore/components/controls/DateFilterControl/components/CustomFrame.tsx
@@ -16,8 +16,6 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { useEffect, useState } from 'react';
-import { useSelector } from 'react-redux';
import { isInteger } from 'lodash';
import { t, customTimeRangeDecode } from '@superset-ui/core';
import { InfoTooltipWithTrigger } from '@superset-ui/chart-controls';
@@ -35,23 +33,19 @@ import {
MIDNIGHT,
customTimeRangeEncode,
dttmToDayjs,
- 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';
import Loading from 'src/components/Loading';
-import dayjs, { Dayjs } from 'dayjs';
+import { Dayjs } from 'dayjs';
import { AntdThemeProvider } from 'src/components/AntdThemeProvider';
-import { Locale } from 'antd-v5/es/locale';
+import { useLocale } from 'src/hooks/useLocale';
export function CustomFrame(props: FrameComponentProps) {
const { customRange, matchedFlag } = customTimeRangeDecode(props.value);
- const [datePickerLocale, setDatePickerLocale] = useState<
- Locale | undefined | null
- >(null);
+ const datePickerLocale = useLocale();
if (!matchedFlag) {
props.onChange(customTimeRangeEncode(customRange));
}
@@ -113,31 +107,6 @@ export function CustomFrame(props: FrameComponentProps) {
}
}
- // check if there is a locale defined for explore
- const localFromFlaskBabel = useSelector(
- (state: ExplorePageState) => state?.common?.locale,
- );
-
- // An undefined datePickerLocale is acceptable if no match is found in the LOCALE_MAPPING[localFromFlaskBabel] lookup
- // and will fall back to antd's default locale when the antd DataPicker's prop locale === undefined
- // This also protects us from the case where state is populated with a locale that antd locales does not recognize
- useEffect(() => {
- if (datePickerLocale === null) {
- if (localFromFlaskBabel && LOCALE_MAPPING[localFromFlaskBabel]) {
- LOCALE_MAPPING[localFromFlaskBabel]()
- .then((locale: { default: Locale }) => {
- setDatePickerLocale(locale.default);
- import(`dayjs/locale/${localFromFlaskBabel}`).then(() => {
- dayjs.locale(localFromFlaskBabel);
- });
- })
- .catch(() => setDatePickerLocale(undefined));
- } else {
- setDatePickerLocale(undefined);
- }
- }
- }, [datePickerLocale, localFromFlaskBabel]);
-
if (datePickerLocale === null) {
return ;
}
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 0d37ae69133f1..4a116fb65e444 100644
--- a/superset-frontend/src/explore/components/controls/DateFilterControl/utils/constants.ts
+++ b/superset-frontend/src/explore/components/controls/DateFilterControl/utils/constants.ts
@@ -141,23 +141,6 @@ export const MIDNIGHT = extendedDayjs()
.startOf('day')
.format(DAYJS_FORMAT);
-export const LOCALE_MAPPING = {
- en: () => import('antd-v5/locale/en_US'),
- fr: () => import('antd-v5/locale/fr_FR'),
- es: () => import('antd-v5/locale/es_ES'),
- it: () => import('antd-v5/locale/it_IT'),
- zh: () => import('antd-v5/locale/zh_CN'),
- ja: () => import('antd-v5/locale/ja_JP'),
- de: () => import('antd-v5/locale/de_DE'),
- pt: () => import('antd-v5/locale/pt_PT'),
- pt_BR: () => import('antd-v5/locale/pt_BR'),
- ru: () => import('antd-v5/locale/ru_RU'),
- ko: () => import('antd-v5/locale/ko_KR'),
- sk: () => import('antd-v5/locale/sk_SK'),
- sl: () => import('antd-v5/locale/sl_SI'),
- nl: () => import('antd-v5/locale/nl_NL'),
-};
-
export enum DateFilterTestKey {
CommonFrame = 'common-frame',
ModalOverlay = 'modal-overlay',
diff --git a/superset-frontend/src/hooks/useLocale.ts b/superset-frontend/src/hooks/useLocale.ts
new file mode 100644
index 0000000000000..43b7505b18ff5
--- /dev/null
+++ b/superset-frontend/src/hooks/useLocale.ts
@@ -0,0 +1,71 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { Locale } from 'antd-v5/es/locale';
+import dayjs from 'dayjs';
+import { useEffect, useState } from 'react';
+import { useSelector } from 'react-redux';
+import { ExplorePageState } from 'src/explore/types';
+
+export const LOCALE_MAPPING = {
+ en: () => import('antd-v5/locale/en_US'),
+ fr: () => import('antd-v5/locale/fr_FR'),
+ es: () => import('antd-v5/locale/es_ES'),
+ it: () => import('antd-v5/locale/it_IT'),
+ zh: () => import('antd-v5/locale/zh_CN'),
+ ja: () => import('antd-v5/locale/ja_JP'),
+ de: () => import('antd-v5/locale/de_DE'),
+ pt: () => import('antd-v5/locale/pt_PT'),
+ pt_BR: () => import('antd-v5/locale/pt_BR'),
+ ru: () => import('antd-v5/locale/ru_RU'),
+ ko: () => import('antd-v5/locale/ko_KR'),
+ sk: () => import('antd-v5/locale/sk_SK'),
+ sl: () => import('antd-v5/locale/sl_SI'),
+ nl: () => import('antd-v5/locale/nl_NL'),
+};
+
+export const useLocale = (): Locale | undefined | null => {
+ const [datePickerLocale, setDatePickerLocale] = useState<
+ Locale | undefined | null
+ >(null);
+
+ // Retrieve the locale from Redux store
+ const localFromFlaskBabel = useSelector(
+ (state: ExplorePageState) => state?.common?.locale,
+ );
+
+ useEffect(() => {
+ if (datePickerLocale === null) {
+ if (localFromFlaskBabel && LOCALE_MAPPING[localFromFlaskBabel]) {
+ LOCALE_MAPPING[localFromFlaskBabel]()
+ .then((locale: { default: Locale }) => {
+ setDatePickerLocale(locale.default);
+ import(`dayjs/locale/${localFromFlaskBabel}.js`).then(() => {
+ dayjs.locale(localFromFlaskBabel);
+ });
+ })
+ .catch(() => setDatePickerLocale(undefined));
+ } else {
+ setDatePickerLocale(undefined);
+ }
+ }
+ }, [datePickerLocale, localFromFlaskBabel]);
+
+ return datePickerLocale;
+};
diff --git a/superset-frontend/webpack.config.js b/superset-frontend/webpack.config.js
index 14b2866876a2b..4384e0638b2c5 100644
--- a/superset-frontend/webpack.config.js
+++ b/superset-frontend/webpack.config.js
@@ -160,11 +160,6 @@ const plugins = [
chunks: [],
filename: '500.html',
}),
- // Dayjs locales to keep
- new webpack.ContextReplacementPlugin(
- /dayjs[/\\]locale$/,
- new RegExp(`^./(${getAvailableTranslationCodes().join('|')})$`),
- ),
];
if (!process.env.CI) {