diff --git a/components/calendar/generateCalendar.tsx b/components/calendar/generateCalendar.tsx index e9884cbe8cd6..c2bba1abaaa5 100644 --- a/components/calendar/generateCalendar.tsx +++ b/components/calendar/generateCalendar.tsx @@ -10,7 +10,7 @@ import type { import useMergedState from 'rc-util/lib/hooks/useMergedState'; import * as React from 'react'; import { ConfigContext } from '../config-provider'; -import LocaleReceiver from '../locale/LocaleReceiver'; +import useLocale from '../locale/useLocale'; import CalendarHeader from './Header'; import enUS from './locale/en_US'; @@ -236,60 +236,57 @@ function generateCalendar(generateConfig: GenerateConfig) { [monthFullCellRender, monthCellRender], ); + const contextLocale = useLocale('Calendar', getDefaultLocale); + return wrapSSR( - - {(contextLocale) => ( -
- {headerRender ? ( - headerRender({ - value: mergedValue, - type: mergedMode, - onChange: onInternalSelect, - onTypeChange: triggerModeChange, - }) - ) : ( - - )} - - monthRender(date, contextLocale.lang)} - onSelect={onInternalSelect} - mode={panelMode} - picker={panelMode} - disabledDate={mergedDisabledDate} - hideHeader - /> -
+
+ {headerRender ? ( + headerRender({ + value: mergedValue, + type: mergedMode, + onChange: onInternalSelect, + onTypeChange: triggerModeChange, + }) + ) : ( + )} - , + monthRender(date, contextLocale?.lang)} + onSelect={onInternalSelect} + mode={panelMode} + picker={panelMode} + disabledDate={mergedDisabledDate} + hideHeader + /> +
, ); }; diff --git a/components/config-provider/index.tsx b/components/config-provider/index.tsx index d3e20a0dac15..aca1c134902b 100644 --- a/components/config-provider/index.tsx +++ b/components/config-provider/index.tsx @@ -3,13 +3,15 @@ import IconContext from '@ant-design/icons/lib/components/Context'; import { FormProvider as RcFormProvider } from 'rc-field-form'; import type { ValidateMessages } from 'rc-field-form/lib/interface'; import useMemo from 'rc-util/lib/hooks/useMemo'; -import * as React from 'react'; import type { ReactElement } from 'react'; +import * as React from 'react'; import type { Options } from 'scroll-into-view-if-needed'; +import warning from '../_util/warning'; import type { RequiredMark } from '../form/Form'; import type { Locale } from '../locale'; import LocaleProvider, { ANT_MARK } from '../locale'; -import LocaleReceiver from '../locale/LocaleReceiver'; +import type { LocaleContextProps } from '../locale/context'; +import LocaleContext from '../locale/context'; import defaultLocale from '../locale/en_US'; import { DesignTokenContext } from '../theme/internal'; import defaultSeedToken from '../theme/themes/seed'; @@ -18,12 +20,11 @@ import { ConfigConsumer, ConfigContext, defaultIconPrefixCls } from './context'; import { registerTheme } from './cssVariables'; import type { RenderEmptyHandler } from './defaultRenderEmpty'; import { DisabledContextProvider } from './DisabledContext'; +import useConfig from './hooks/useConfig'; import useTheme from './hooks/useTheme'; import type { SizeType } from './SizeContext'; import SizeContext, { SizeContextProvider } from './SizeContext'; import useStyle from './style'; -import useConfig from './hooks/useConfig'; -import warning from '../_util/warning'; export { type RenderEmptyHandler, @@ -316,18 +317,11 @@ const ConfigProvider: React.FC & { /** @deprecated Please use `ConfigProvider.useConfig().componentSize` instead */ SizeContext: typeof SizeContext; config: typeof setGlobalConfig; - useConfig: typeof useConfig; -} = (props) => ( - - {(_, __, legacyLocale) => ( - - {(context) => ( - - )} - - )} - -); +} = (props) => { + const context = React.useContext(ConfigContext); + const antLocale = React.useContext(LocaleContext); + return ; +}; ConfigProvider.ConfigContext = ConfigContext; ConfigProvider.SizeContext = SizeContext; diff --git a/components/date-picker/generatePicker/generateRangePicker.tsx b/components/date-picker/generatePicker/generateRangePicker.tsx index aff3e16c8934..8974388b0b55 100644 --- a/components/date-picker/generatePicker/generateRangePicker.tsx +++ b/components/date-picker/generatePicker/generateRangePicker.tsx @@ -13,13 +13,13 @@ import { ConfigContext } from '../../config-provider'; import DisabledContext from '../../config-provider/DisabledContext'; import SizeContext from '../../config-provider/SizeContext'; import { FormItemInputContext } from '../../form/context'; +import useLocale from '../../locale/useLocale'; import { useCompactItemContext } from '../../space/Compact'; -import LocaleReceiver from '../../locale/LocaleReceiver'; import { getMergedStatus, getStatusClassNames } from '../../_util/statusUtils'; +import warning from '../../_util/warning'; import enUS from '../locale/en_US'; import { getRangePlaceholder, transPlacement2DropdownAlign } from '../util'; import type { CommonPickerMethods, PickerComponentClass } from './interface'; -import warning from '../../_util/warning'; import useStyle from '../style'; @@ -102,57 +102,53 @@ export default function generateRangePicker(generateConfig: GenerateCo blur: () => innerRef.current?.blur(), })); + const contextLocale = useLocale('Calendar', enUS); + + const locale = { ...contextLocale, ...props.locale! }; + return wrapSSR( - - {(contextLocale) => { - const locale = { ...contextLocale, ...props.locale }; - - return ( - - separator={ - - - - } - disabled={mergedDisabled} - ref={innerRef} - dropdownAlign={transPlacement2DropdownAlign(direction, placement)} - placeholder={getRangePlaceholder(locale, picker, placeholder)} - suffixIcon={suffixNode} - clearIcon={} - prevIcon={} - nextIcon={} - superPrevIcon={} - superNextIcon={} - allowClear - transitionName={`${rootPrefixCls}-slide-up`} - {...restProps} - {...additionalOverrideProps} - className={classNames( - { - [`${prefixCls}-${mergedSize}`]: mergedSize, - [`${prefixCls}-borderless`]: !bordered, - }, - getStatusClassNames( - prefixCls as string, - getMergedStatus(contextStatus, customStatus), - hasFeedback, - ), - hashId, - compactItemClassnames, - className, - )} - locale={locale.lang} - prefixCls={prefixCls} - getPopupContainer={customGetPopupContainer || getPopupContainer} - generateConfig={generateConfig} - components={Components} - direction={direction} - dropdownClassName={classNames(hashId, popupClassName || dropdownClassName)} - /> - ); - }} - , + + separator={ + + + + } + disabled={mergedDisabled} + ref={innerRef} + dropdownAlign={transPlacement2DropdownAlign(direction, placement)} + placeholder={getRangePlaceholder(locale, picker, placeholder)} + suffixIcon={suffixNode} + clearIcon={} + prevIcon={} + nextIcon={} + superPrevIcon={} + superNextIcon={} + allowClear + transitionName={`${rootPrefixCls}-slide-up`} + {...restProps} + {...additionalOverrideProps} + className={classNames( + { + [`${prefixCls}-${mergedSize}`]: mergedSize, + [`${prefixCls}-borderless`]: !bordered, + }, + getStatusClassNames( + prefixCls as string, + getMergedStatus(contextStatus, customStatus), + hasFeedback, + ), + hashId, + compactItemClassnames, + className, + )} + locale={locale.lang} + prefixCls={prefixCls} + getPopupContainer={customGetPopupContainer || getPopupContainer} + generateConfig={generateConfig} + components={Components} + direction={direction} + dropdownClassName={classNames(hashId, popupClassName || dropdownClassName)} + />, ); }); diff --git a/components/date-picker/generatePicker/generateSinglePicker.tsx b/components/date-picker/generatePicker/generateSinglePicker.tsx index 1a500353a12a..68b5bff9e99f 100644 --- a/components/date-picker/generatePicker/generateSinglePicker.tsx +++ b/components/date-picker/generatePicker/generateSinglePicker.tsx @@ -13,7 +13,7 @@ import { ConfigContext } from '../../config-provider'; import DisabledContext from '../../config-provider/DisabledContext'; import SizeContext from '../../config-provider/SizeContext'; import { FormItemInputContext } from '../../form/context'; -import LocaleReceiver from '../../locale/LocaleReceiver'; +import useLocale from '../../locale/useLocale'; import { useCompactItemContext } from '../../space/Compact'; import type { InputStatus } from '../../_util/statusUtils'; import { getMergedStatus, getStatusClassNames } from '../../_util/statusUtils'; @@ -122,58 +122,54 @@ export default function generatePicker(generateConfig: GenerateConfig< ); + const contextLocale = useLocale('DatePicker', enUS); + + const locale = { ...contextLocale, ...props.locale! }; + return wrapSSR( - - {(contextLocale) => { - const locale = { ...contextLocale, ...props.locale }; - - return ( - - ref={innerRef} - placeholder={getPlaceholder(locale, mergedPicker, placeholder)} - suffixIcon={suffixNode} - dropdownAlign={transPlacement2DropdownAlign(direction, placement)} - clearIcon={} - prevIcon={} - nextIcon={} - superPrevIcon={} - superNextIcon={} - allowClear - transitionName={`${rootPrefixCls}-slide-up`} - {...additionalProps} - {...restProps} - {...additionalOverrideProps} - locale={locale!.lang} - className={classNames( - { - [`${prefixCls}-${mergedSize}`]: mergedSize, - [`${prefixCls}-borderless`]: !bordered, - }, - getStatusClassNames( - prefixCls as string, - getMergedStatus(contextStatus, customStatus), - hasFeedback, - ), - hashId, - compactItemClassnames, - className, - rootClassName, - )} - prefixCls={prefixCls} - getPopupContainer={customizeGetPopupContainer || getPopupContainer} - generateConfig={generateConfig} - components={Components} - direction={direction} - disabled={mergedDisabled} - dropdownClassName={classNames( - hashId, - rootClassName, - popupClassName || dropdownClassName, - )} - /> - ); - }} - , + + ref={innerRef} + placeholder={getPlaceholder(locale, mergedPicker, placeholder)} + suffixIcon={suffixNode} + dropdownAlign={transPlacement2DropdownAlign(direction, placement)} + clearIcon={} + prevIcon={} + nextIcon={} + superPrevIcon={} + superNextIcon={} + allowClear + transitionName={`${rootPrefixCls}-slide-up`} + {...additionalProps} + {...restProps} + {...additionalOverrideProps} + locale={locale!.lang} + className={classNames( + { + [`${prefixCls}-${mergedSize}`]: mergedSize, + [`${prefixCls}-borderless`]: !bordered, + }, + getStatusClassNames( + prefixCls as string, + getMergedStatus(contextStatus, customStatus), + hasFeedback, + ), + hashId, + compactItemClassnames, + className, + rootClassName, + )} + prefixCls={prefixCls} + getPopupContainer={customizeGetPopupContainer || getPopupContainer} + generateConfig={generateConfig} + components={Components} + direction={direction} + disabled={mergedDisabled} + dropdownClassName={classNames( + hashId, + rootClassName, + popupClassName || dropdownClassName, + )} + />, ); }, ); diff --git a/components/empty/index.tsx b/components/empty/index.tsx index 01031a980207..41d3a376d64e 100644 --- a/components/empty/index.tsx +++ b/components/empty/index.tsx @@ -1,7 +1,7 @@ import classNames from 'classnames'; import * as React from 'react'; import { ConfigContext } from '../config-provider'; -import LocaleReceiver from '../locale/LocaleReceiver'; +import useLocale from '../locale/useLocale'; import DefaultEmptyImg from './empty'; import SimpleEmptyImg from './simple'; @@ -46,43 +46,39 @@ const Empty: CompoundedComponent = ({ const prefixCls = getPrefixCls('empty', customizePrefixCls); const [wrapSSR, hashId] = useStyle(prefixCls); - return wrapSSR( - - {(locale: TransferLocale) => { - const des = typeof description !== 'undefined' ? description : locale.description; - const alt = typeof des === 'string' ? des : 'empty'; + const locale = useLocale('Empty'); + + const des = typeof description !== 'undefined' ? description : locale?.description; + const alt = typeof des === 'string' ? des : 'empty'; - let imageNode: React.ReactNode = null; + let imageNode: React.ReactNode = null; - if (typeof image === 'string') { - imageNode = {alt}; - } else { - imageNode = image; - } + if (typeof image === 'string') { + imageNode = {alt}; + } else { + imageNode = image; + } - return ( -
-
- {imageNode} -
- {des &&
{des}
} - {children &&
{children}
} -
- ); - }} -
, + return wrapSSR( +
+
+ {imageNode} +
+ {des &&
{des}
} + {children &&
{children}
} +
, ); }; diff --git a/components/form/FormItemLabel.tsx b/components/form/FormItemLabel.tsx index 3a3298242819..c0d696298d17 100644 --- a/components/form/FormItemLabel.tsx +++ b/components/form/FormItemLabel.tsx @@ -3,8 +3,8 @@ import classNames from 'classnames'; import * as React from 'react'; import type { ColProps } from '../grid/col'; import Col from '../grid/col'; -import { useLocaleReceiver } from '../locale/LocaleReceiver'; import defaultLocale from '../locale/en_US'; +import useLocale from '../locale/useLocale'; import type { TooltipProps } from '../tooltip'; import Tooltip from '../tooltip'; import type { FormContextProps } from './context'; @@ -53,7 +53,7 @@ const FormItemLabel: React.FC { - const [formLocale] = useLocaleReceiver('Form'); + const formLocale = useLocale('Form'); const { vertical, diff --git a/components/locale-provider/LocaleReceiver.ts b/components/locale-provider/LocaleReceiver.ts index 50d1d6201e32..fd15dc9552f0 100644 --- a/components/locale-provider/LocaleReceiver.ts +++ b/components/locale-provider/LocaleReceiver.ts @@ -1,6 +1,6 @@ // locale-provider 文件夹的移除需要修改 @ant-design/tools 和 antd-img-crop -import LocaleReceiver from '../locale/LocaleReceiver'; +import useLocale from '../locale/useLocale'; -export * from '../locale/LocaleReceiver'; +export * from '../locale/useLocale'; -export default LocaleReceiver; +export default useLocale; diff --git a/components/locale/LocaleReceiver.ts b/components/locale/LocaleReceiver.ts deleted file mode 100644 index 1d59fb6350d0..000000000000 --- a/components/locale/LocaleReceiver.ts +++ /dev/null @@ -1,64 +0,0 @@ -import * as React from 'react'; -import type { Locale } from '.'; -import type { LocaleContextProps } from './context'; -import LocaleContext from './context'; -import defaultLocaleData from './en_US'; - -export type LocaleComponentName = Exclude; - -export interface LocaleReceiverProps { - componentName?: C; - defaultLocale?: Locale[C] | (() => Locale[C]); - children: ( - locale: NonNullable, - localeCode: string, - fullLocale: Locale, - ) => React.ReactElement; -} - -const LocaleReceiver = ( - props: LocaleReceiverProps, -) => { - const { componentName = 'global' as C, defaultLocale, children } = props; - const antLocale = React.useContext(LocaleContext); - - const getLocale = React.useMemo>(() => { - const locale = defaultLocale || defaultLocaleData[componentName]; - const localeFromContext = antLocale?.[componentName] ?? {}; - return { - ...(locale instanceof Function ? locale() : locale), - ...(localeFromContext || {}), - }; - }, [componentName, defaultLocale, antLocale]); - - const getLocaleCode = React.useMemo(() => { - const localeCode = antLocale && antLocale.locale; - // Had use LocaleProvide but didn't set locale - if (antLocale && antLocale.exist && !localeCode) { - return defaultLocaleData.locale; - } - return localeCode!; - }, [antLocale]); - - return children(getLocale, getLocaleCode, antLocale!); -}; - -export default LocaleReceiver; - -export const useLocaleReceiver = ( - componentName: C, - defaultLocale?: Locale[C] | (() => Locale[C]), -): [Locale[C]] => { - const antLocale = React.useContext(LocaleContext); - - const getLocale = React.useMemo>(() => { - const locale = defaultLocale || defaultLocaleData[componentName]; - const localeFromContext = antLocale?.[componentName] ?? {}; - return { - ...(typeof locale === 'function' ? locale() : locale), - ...(localeFromContext || {}), - }; - }, [componentName, defaultLocale, antLocale]); - - return [getLocale]; -}; diff --git a/components/locale/useLocale.ts b/components/locale/useLocale.ts new file mode 100644 index 000000000000..c3b5b01ddd93 --- /dev/null +++ b/components/locale/useLocale.ts @@ -0,0 +1,24 @@ +import * as React from 'react'; +import type { Locale } from '.'; +import type { LocaleContextProps } from './context'; +import LocaleContext from './context'; +import defaultLocaleData from './en_US'; + +export type LocaleComponentName = Exclude; + +const useLocale = ( + componentName: C, + defaultLocale?: Locale[C] | (() => Locale[C]), +): Locale[C] => { + const antLocale = React.useContext(LocaleContext); + return React.useMemo>(() => { + const locale = defaultLocale || defaultLocaleData[componentName]; + const localeFromContext = antLocale?.[componentName] ?? {}; + return { + ...(typeof locale === 'function' ? locale() : locale), + ...(localeFromContext || {}), + }; + }, [componentName, defaultLocale, antLocale]); +}; + +export default useLocale; diff --git a/components/modal/ConfirmDialog.tsx b/components/modal/ConfirmDialog.tsx index 6e5a8b47ca90..b5580743e472 100644 --- a/components/modal/ConfirmDialog.tsx +++ b/components/modal/ConfirmDialog.tsx @@ -5,7 +5,7 @@ import InfoCircleFilled from '@ant-design/icons/InfoCircleFilled'; import classNames from 'classnames'; import * as React from 'react'; import ConfigProvider from '../config-provider'; -import LocaleReceiver from '../locale/LocaleReceiver'; +import useLocale from '../locale/useLocale'; import ActionButton from '../_util/ActionButton'; import { getTransitionName } from '../_util/motion'; import warning from '../_util/warning'; @@ -81,57 +81,53 @@ export function ConfirmContent( const autoFocusButton = props.autoFocusButton === null ? false : props.autoFocusButton || 'ok'; - return ( - - {(locale) => { - const mergedLocale = staticLocale || locale; + const locale = useLocale('Modal'); + + const mergedLocale = staticLocale || locale; + + const cancelButton = mergedOkCancel && ( + + {cancelText || mergedLocale?.cancelText} + + ); - const cancelButton = mergedOkCancel && ( + return ( +
+
+ {mergedIcon} + {props.title === undefined ? null : ( + {props.title} + )} +
{props.content}
+
+ {footer !== undefined ? ( + footer + ) : ( +
+ {cancelButton} - {cancelText || mergedLocale?.cancelText} + {okText || (mergedOkCancel ? mergedLocale?.okText : mergedLocale?.justOkText)} - ); - - return ( -
-
- {mergedIcon} - {props.title === undefined ? null : ( - {props.title} - )} -
{props.content}
-
- {footer !== undefined ? ( - footer - ) : ( -
- {cancelButton} - - {okText || (mergedOkCancel ? mergedLocale?.okText : mergedLocale?.justOkText)} - -
- )} -
- ); - }} - +
+ )} +
); } -const ConfirmDialog = (props: ConfirmDialogProps) => { +const ConfirmDialog: React.FC = (props) => { const { close, zIndex, diff --git a/components/modal/Modal.tsx b/components/modal/Modal.tsx index a47f279c4f81..20f5864704d8 100644 --- a/components/modal/Modal.tsx +++ b/components/modal/Modal.tsx @@ -9,7 +9,7 @@ import { NoCompactStyle } from '../space/Compact'; import { getTransitionName } from '../_util/motion'; import { canUseDocElement } from '../_util/styleChecker'; import warning from '../_util/warning'; -import { renderCloseIcon, renderFooter } from './PurePanel'; +import { Footer, renderCloseIcon } from './PurePanel'; import useStyle from './style'; type MousePosition = { x: number; y: number } | null; @@ -209,11 +209,13 @@ const Modal: React.FC = (props) => { prefixCls={prefixCls} rootClassName={classNames(hashId, rootClassName)} wrapClassName={wrapClassNameExtended} - footer={renderFooter({ - ...props, - onOk: handleOk, - onCancel: handleCancel, - })} + footer={ + props.footer === null ? ( + props.footer + ) : ( +