diff --git a/package.json b/package.json
index e2e14dab8..4c44191c6 100644
--- a/package.json
+++ b/package.json
@@ -133,5 +133,6 @@
     },
     "resolutions": {
         "rc-motion": "2.6.2"
-    }
+    },
+    "packageManager": "pnpm@6.32.12"
 }
diff --git a/src/blockHeader/index.tsx b/src/blockHeader/index.tsx
index aa022e15b..72813b6f4 100644
--- a/src/blockHeader/index.tsx
+++ b/src/blockHeader/index.tsx
@@ -3,6 +3,7 @@ import { QuestionCircleOutlined, UpOutlined } from '@ant-design/icons';
 import { Tooltip } from 'antd';
 import classNames from 'classnames';
 
+import useLocale from '../locale/useLocale';
 import './style.scss';
 
 export declare type SizeType = 'small' | 'middle' | undefined;
@@ -59,6 +60,8 @@ const BlockHeader: React.FC<IBlockHeaderProps> = function (props) {
 
     const [expand, setExpand] = useState(defaultExpand);
 
+    const locale = useLocale('BlockHeader');
+
     const preTitleRowCls = `${prefixCls}-title-row`;
 
     const questionTooltip = tooltip && (
@@ -103,7 +106,7 @@ const BlockHeader: React.FC<IBlockHeaderProps> = function (props) {
                 {addonAfter && <div className={`${prefixCls}-addonAfter-box`}>{addonAfter}</div>}
                 {children && (
                     <div className={`${prefixCls}-collapse-box`}>
-                        <div className="text">{expand ? '收起' : '展开'}</div>
+                        <div className="text">{expand ? locale.collapse : locale.expand}</div>
                         <UpOutlined className={`icon ${expand ? 'up' : 'down'}`} />
                     </div>
                 )}
diff --git a/src/configProvider/index.tsx b/src/configProvider/index.tsx
new file mode 100644
index 000000000..d24d70ab0
--- /dev/null
+++ b/src/configProvider/index.tsx
@@ -0,0 +1,9 @@
+import React from 'react';
+
+import { Locale, LocaleContext } from '../locale/useLocale';
+
+const ConfigProvider = ({ locale, children }: { locale: Locale; children: React.ReactNode }) => {
+    return <LocaleContext.Provider value={{ locale }}>{children}</LocaleContext.Provider>;
+};
+
+export default ConfigProvider;
diff --git a/src/copy/index.tsx b/src/copy/index.tsx
index 9622e930e..b7b85f792 100644
--- a/src/copy/index.tsx
+++ b/src/copy/index.tsx
@@ -4,6 +4,7 @@ import { message, Tooltip } from 'antd';
 import classNames from 'classnames';
 import useClippy from 'use-clippy';
 
+import useLocale from '../locale/useLocale';
 import './style.scss';
 
 export interface ICopyProps {
@@ -17,14 +18,15 @@ export interface ICopyProps {
 }
 
 const Copy: React.FC<ICopyProps> = (props) => {
+    const locale = useLocale('Copy');
     const {
         button = <CopyOutlined className="dtc-copy__default-icon" />,
         text,
-        title = '复制',
+        title = locale.copy,
         hideTooltip,
         style,
         className,
-        onCopy = () => message.success('复制成功'),
+        onCopy = () => message.success(locale.copied),
     } = props;
     const [_, setClipboard] = useClippy();
 
diff --git a/src/dropdown/select.tsx b/src/dropdown/select.tsx
index b0b6323a1..8b420894a 100644
--- a/src/dropdown/select.tsx
+++ b/src/dropdown/select.tsx
@@ -6,6 +6,7 @@ import classNames from 'classnames';
 import { isEqual } from 'lodash';
 import List from 'rc-virtual-list';
 
+import useLocale from '../locale/useLocale';
 import './style.scss';
 
 interface IDropdownSelectProps
@@ -31,6 +32,8 @@ export default function Select({
 }: IDropdownSelectProps) {
     const [visible, setVisible] = useState(false);
 
+    const locale = useLocale('Dropdown');
+
     const handleCheckedAll = (e: CheckboxChangeEvent) => {
         if (e.target.checked) {
             onChange?.(options?.map((i) => i.value) || []);
@@ -119,7 +122,7 @@ export default function Select({
                         checked={checkAll}
                         indeterminate={indeterminate}
                     >
-                        全选
+                        {locale.selectAll}
                     </Checkbox>
                 </Col>
                 <Col span={24} className={`${prefix}__menu`}>
@@ -158,10 +161,10 @@ export default function Select({
             </Row>
             <Space size={8} className={`${prefix}__btns`}>
                 <Button size="small" disabled={resetDisabled} onClick={handleReset}>
-                    重置
+                    {locale.resetText}
                 </Button>
                 <Button size="small" type="primary" onClick={handleSubmit}>
-                    确定
+                    {locale.okText}
                 </Button>
             </Space>
         </>
diff --git a/src/errorBoundary/loadError.tsx b/src/errorBoundary/loadError.tsx
index 8d75380d2..b10fbd491 100644
--- a/src/errorBoundary/loadError.tsx
+++ b/src/errorBoundary/loadError.tsx
@@ -1,22 +1,24 @@
 import React from 'react';
 
+import useLocale from '../locale/useLocale';
+
 const LoadError: React.FC = function () {
+    const locale = useLocale('LoadError');
     return (
         <div className="dtc-error" data-testid="test-error">
             <div>
-                
                 <h2 style={{ textAlign: 'center' }} data-testid="test-error">
-                    发现新版本,请
+                    {locale.please}
                     <a
                         onClick={() => {
                             location.reload();
                         }}
                     >
-                        刷新
+                        {locale.refresh}
                     </a>
-                    获取新版本。
+                    {locale.get}
                 </h2>
-                <h4 style={{ textAlign: 'center' }}>若该提示长时间存在,请联系管理员。</h4>
+                <h4 style={{ textAlign: 'center' }}>{locale.title}</h4>
             </div>
         </div>
     );
diff --git a/src/fullscreen/index.tsx b/src/fullscreen/index.tsx
index ece3b7502..97b5ea09f 100644
--- a/src/fullscreen/index.tsx
+++ b/src/fullscreen/index.tsx
@@ -2,6 +2,7 @@ import React, { CSSProperties, HTMLAttributes, ReactNode, useEffect, useState }
 import { Button } from 'antd';
 
 import KeyEventListener from '../keyEventListener';
+import useLocale from '../locale/useLocale';
 import MyIcon from './icon';
 
 const { KeyCombiner } = KeyEventListener;
@@ -44,7 +45,11 @@ export default function Fullscreen({
     ...other
 }: IFullscreenProps) {
     const [isFullScreen, setIsFullScreen] = useState(false);
+
+    const locale = useLocale('Fullscreen');
+
     const customIcon = isFullScreen ? exitFullIcon : fullIcon;
+
     useEffect(() => {
         const propsDom = document.getElementById(target);
         const domEle = propsDom || document.body;
@@ -188,7 +193,7 @@ export default function Fullscreen({
             ) : (
                 <Button onClick={handleFullScreen}>
                     <MyIcon style={iconStyle} type={isFullScreen} themeDark={themeDark} />
-                    {isFullScreen ? '退出全屏' : '全屏'}
+                    {isFullScreen ? locale.exitFull : locale.full}
                 </Button>
             )}
         </KeyCombiner>
diff --git a/src/globalLoading/index.tsx b/src/globalLoading/index.tsx
index 1269cf757..9cc2ff50b 100644
--- a/src/globalLoading/index.tsx
+++ b/src/globalLoading/index.tsx
@@ -1,6 +1,7 @@
 import React from 'react';
 import classNames from 'classnames';
 
+import useLocale from '../locale/useLocale';
 import './style.scss';
 
 export interface IGlobalLoadingProps {
@@ -12,8 +13,10 @@ export interface IGlobalLoadingProps {
 }
 
 const GlobalLoading: React.FC<IGlobalLoadingProps> = function (props) {
+    const locale = useLocale('GlobalLoading');
+
     const {
-        loadingTitle = '应用加载中,请等候~',
+        loadingTitle = locale.loading,
         mainBackground = '#F2F7FA',
         circleBackground = '#1D78FF',
         titleColor = '#3D446E',
diff --git a/src/index.ts b/src/index.ts
index e284f6601..5c0822dde 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,5 +1,6 @@
 export { default as BlockHeader } from './blockHeader';
 export { default as CollapsibleActionItems } from './collapsibleActionItems';
+export { default as ConfigProvider } from './configProvider';
 export { default as ContextMenu } from './contextMenu';
 export { default as useCookieListener } from './cookies';
 export { default as Copy } from './copy';
@@ -13,6 +14,8 @@ export { default as Fullscreen } from './fullscreen';
 export { default as GlobalLoading } from './globalLoading';
 export { default as Input } from './input';
 export { default as KeyEventListener } from './keyEventListener';
+export { default as enUS } from './locale/en-US';
+export { default as zhCN } from './locale/zh-CN';
 export { default as MarkdownRender } from './markdownRender';
 export { default as Modal } from './modal';
 export { default as MxGraphContainer, WIDGETS_PREFIX } from './mxGraph';
diff --git a/src/input/match.tsx b/src/input/match.tsx
index a13c1c176..020ee844e 100644
--- a/src/input/match.tsx
+++ b/src/input/match.tsx
@@ -2,6 +2,7 @@ import React, { useState } from 'react';
 import { Input, type InputProps, Tooltip } from 'antd';
 import classNames from 'classnames';
 
+import useLocale from '../locale/useLocale';
 import { CaseSensitiveIcon, FrontIcon, PreciseIcon, TailIcon } from './icons';
 import './match.scss';
 
@@ -29,30 +30,11 @@ interface IMatchProps extends Omit<InputProps, 'suffix'> {
     onSearch?: (value: string, searchType: SearchType) => void;
 }
 
-const searchTypeList = [
-    {
-        key: 'caseSensitive',
-        tip: '区分大小写匹配',
-    },
-    {
-        key: 'precise',
-        tip: '精确匹配',
-    },
-    {
-        key: 'front',
-        tip: '头部匹配',
-    },
-    {
-        key: 'tail',
-        tip: '尾部匹配',
-    },
-] as const;
-
 export default function Match({
     className,
     value,
     searchType,
-    filterOptions = searchTypeList.map((i) => i.key),
+    filterOptions: propFilterOptions,
     onTypeChange,
     onSearch,
     onChange,
@@ -62,12 +44,35 @@ export default function Match({
     const [internalValue, setValue] = useState<string>('');
     const [internalSearchType, setSearchType] = useState<SearchType>('fuzzy');
 
+    const locale = useLocale('Input');
+
     const handleTypeChange = (key: SearchType) => {
         const next = realSearchType === key ? 'fuzzy' : key;
         onTypeChange?.(next);
         setSearchType(next);
     };
 
+    const searchTypeList = [
+        {
+            key: 'caseSensitive',
+            tip: locale.case,
+        },
+        {
+            key: 'precise',
+            tip: locale.precise,
+        },
+        {
+            key: 'front',
+            tip: locale.front,
+        },
+        {
+            key: 'tail',
+            tip: locale.tail,
+        },
+    ] as const;
+
+    const filterOptions = propFilterOptions || searchTypeList.map((i) => i.key);
+
     const options = searchTypeList.filter((i) => filterOptions.includes(i.key));
 
     const realSearchType = searchType || internalSearchType;
diff --git a/src/locale/en-US.ts b/src/locale/en-US.ts
new file mode 100644
index 000000000..264b9df7d
--- /dev/null
+++ b/src/locale/en-US.ts
@@ -0,0 +1,57 @@
+import { Locale } from './useLocale';
+
+const localeValues: Locale = {
+    locale: 'en-US',
+    BlockHeader: {
+        expand: 'Expand',
+        collapse: 'Collapse',
+    },
+
+    Copy: {
+        copied: 'Copied',
+
+        copy: 'Copy',
+    },
+    Fullscreen: {
+        exitFull: 'Exit Full Screen',
+        full: 'Full Screen',
+    },
+    GlobalLoading: {
+        loading: 'The application is loading, please wait~',
+    },
+    LoadError: {
+        please: 'A new version has been found. Please',
+        get: 'to get the new version.',
+        refresh: ' refresh ',
+        title: 'If this prompt persists for a long time, please contact the administrator.',
+    },
+    Modal: {
+        okText: 'Ok',
+        cancelText: 'Cancel',
+    },
+    Dropdown: {
+        resetText: 'Cancel',
+        okText: 'Ok',
+        selectAll: 'Select All',
+    },
+    Input: {
+        case: 'Case-sensitive match',
+        precise: 'Exact match',
+        front: 'Head match',
+        tail: 'Tail match',
+    },
+    MxGraph: {
+        newNode: 'New node',
+    },
+    NotFound: {
+        description: 'Dear, did you go to the wrong place?',
+    },
+    SpreadSheet: {
+        description: 'No Data',
+        copy: 'Copy values',
+        copyCol: 'Copy column names',
+        copyAll: 'Copy values ​​and column names',
+    },
+};
+
+export default localeValues;
diff --git a/src/locale/useLocale.tsx b/src/locale/useLocale.tsx
new file mode 100644
index 000000000..d9ecc517f
--- /dev/null
+++ b/src/locale/useLocale.tsx
@@ -0,0 +1,63 @@
+import { createContext, useContext, useMemo } from 'react';
+
+import defaultLocaleData from './zh-CN';
+
+export interface Locale {
+    locale: string;
+    BlockHeader: { expand: string; collapse: string };
+    Copy: { copied: string; copy: string };
+    Dropdown: { selectAll: string; resetText: string; okText: string };
+    Fullscreen: { exitFull: string; full: string };
+    GlobalLoading: { loading: string };
+    Input: {
+        case: string;
+        precise: string;
+        front: string;
+        tail: string;
+    };
+    LoadError: {
+        please: string;
+        get: string;
+        refresh: string;
+        title: string;
+    };
+    Modal: {
+        okText: string;
+        cancelText: string;
+    };
+    MxGraph: { newNode: string };
+    NotFound: {
+        description: string;
+    };
+    SpreadSheet: {
+        description: string;
+        copy: string;
+        copyCol: string;
+        copyAll: string;
+    };
+}
+
+export interface LocaleContextProps {
+    locale: Locale;
+}
+
+export const LocaleContext = createContext<LocaleContextProps>({ locale: {} as Locale });
+
+export type LocaleComponentName = keyof Locale;
+
+const useLocale = <C extends LocaleComponentName = LocaleComponentName>(
+    componentName: C
+): NonNullable<Locale[C]> => {
+    const fullLocale = useContext<LocaleContextProps>(LocaleContext);
+
+    const getLocale = useMemo(() => {
+        const locale = defaultLocaleData[componentName] ?? {};
+        const localeFromContext = fullLocale?.locale[componentName] ?? {};
+
+        return Object.assign({}, locale, localeFromContext) as NonNullable<Locale[C]>;
+    }, [componentName, fullLocale]);
+
+    return getLocale;
+};
+
+export default useLocale;
diff --git a/src/locale/zh-CN.ts b/src/locale/zh-CN.ts
new file mode 100644
index 000000000..ac716da58
--- /dev/null
+++ b/src/locale/zh-CN.ts
@@ -0,0 +1,51 @@
+import { Locale } from './useLocale';
+
+const localeValues: Locale = {
+    locale: 'zh-CN',
+    BlockHeader: {
+        expand: '展开',
+        collapse: '收起',
+    },
+    Copy: {
+        copied: '复制成功',
+        copy: '复制',
+    },
+    Dropdown: { selectAll: '全选', resetText: '重置', okText: '确定' },
+    Fullscreen: {
+        exitFull: '退出全屏',
+        full: '全屏',
+    },
+    GlobalLoading: {
+        loading: '应用加载中,请等候~',
+    },
+    LoadError: {
+        please: '发现新版本,请',
+        get: '获取新版本。',
+        refresh: '刷新',
+        title: '若该提示长时间存在,请联系管理员。',
+    },
+    Input: {
+        case: '区分大小写匹配',
+        precise: '精确匹配',
+        front: '头部匹配',
+        tail: '尾部匹配',
+    },
+    Modal: {
+        okText: '确定',
+        cancelText: '取消',
+    },
+    MxGraph: {
+        newNode: '新节点',
+    },
+    NotFound: {
+        description: '亲,是不是走错地方了?',
+    },
+    SpreadSheet: {
+        description: '暂无数据',
+        copy: '复制值',
+        copyCol: '复制列名',
+        copyAll: '复制列名和值',
+    },
+};
+
+export default localeValues;
diff --git a/src/modal/form.tsx b/src/modal/form.tsx
index f0dfcf518..885e2efd0 100644
--- a/src/modal/form.tsx
+++ b/src/modal/form.tsx
@@ -2,6 +2,7 @@ import React, { ReactElement, useMemo } from 'react';
 import { FormProps, Modal, ModalProps } from 'antd';
 
 import Form from '../form';
+import useLocale from '../locale/useLocale';
 import Utils from '../utils';
 import { FORM_PROPS, MODAL_PROPS } from '../utils/antdProps';
 
@@ -23,9 +24,11 @@ export interface IModalFormProps<Values = any>
 }
 
 const ModalForm = (props: IModalFormProps) => {
+    const locale = useLocale('Modal');
+
     const {
-        okText = '确定',
-        cancelText = '取消',
+        okText = locale.okText,
+        cancelText = locale.cancelText,
         layout = 'vertical',
         maskClosable = false,
         children,
diff --git a/src/mxGraph/index.tsx b/src/mxGraph/index.tsx
index 2822141fd..38ee86fc6 100644
--- a/src/mxGraph/index.tsx
+++ b/src/mxGraph/index.tsx
@@ -20,6 +20,7 @@ import {
     mxPopupMenuHandler,
 } from 'mxgraph';
 
+import useLocale from '../locale/useLocale';
 import MxFactory from './factory';
 import './style.scss';
 
@@ -293,6 +294,8 @@ function MxGraphContainer<T extends IMxGraphData>(
     const keybindingsRef = useRef<IKeyDownConfig[]>([]);
     const [current, setCurrent] = useState<null | T>(null);
 
+    const locale = useLocale('MxGraph');
+
     useImperativeHandle(ref, () => ({
         /**
          * 在某一位置插入节点
@@ -427,7 +430,7 @@ function MxGraphContainer<T extends IMxGraphData>(
                 onGetPreview?.(node) ||
                 (() => {
                     const dom = document.createElement('div');
-                    dom.innerHTML = `<span class="preview-title">新节点</span>`;
+                    dom.innerHTML = `<span class="preview-title">${locale.newNode}</span>`;
                     return dom;
                 })();
 
diff --git a/src/notFound/index.tsx b/src/notFound/index.tsx
index 67fb6d00c..08cd61952 100644
--- a/src/notFound/index.tsx
+++ b/src/notFound/index.tsx
@@ -1,13 +1,15 @@
 import React from 'react';
 import { FrownOutlined } from '@ant-design/icons';
 
+import useLocale from '../locale/useLocale';
 import './style.scss';
 
 const NotFound: React.FC<any> = function () {
+    const locale = useLocale('NotFound');
     return (
         <div className="dtc-not-found">
             <h1>
-                <FrownOutlined /> 亲,是不是走错地方了?
+                <FrownOutlined /> {locale.description}
             </h1>
         </div>
     );
diff --git a/src/spreadSheet/index.tsx b/src/spreadSheet/index.tsx
index 758935477..991465743 100644
--- a/src/spreadSheet/index.tsx
+++ b/src/spreadSheet/index.tsx
@@ -4,6 +4,7 @@ import { HotTable } from '@handsontable/react';
 import classNames from 'classnames';
 import 'handsontable/languages/zh-CN.js';
 
+import useLocale from '../locale/useLocale';
 import CopyUtils from '../utils/copy';
 import 'handsontable/dist/handsontable.full.css';
 import './style.scss';
@@ -36,7 +37,10 @@ const SpreadSheet: React.FC<ISpreadSheetProps> = forwardRef(
         const copyUtils = new CopyUtils();
         const _timer = useRef<NodeJS.Timeout>();
         const { copyTypes = [], ...restProps } = options || {};
+
         useImperativeHandle(ref, () => tableRef.current);
+        const locale = useLocale('SpreadSheet');
+
         useEffect(() => {
             if (tableRef.current) {
                 removeRenderClock();
@@ -57,7 +61,7 @@ const SpreadSheet: React.FC<ISpreadSheetProps> = forwardRef(
             let showData = data;
             if (!showData?.length) {
                 const emptyArr = new Array(columns.length).fill('', 0, columns.length);
-                emptyArr[0] = '暂无数据';
+                emptyArr[0] = locale.description;
                 showData = [emptyArr];
             }
             return showData;
@@ -128,21 +132,21 @@ const SpreadSheet: React.FC<ISpreadSheetProps> = forwardRef(
             };
 
             const copyDataItem = {
-                name: '复制值',
+                name: locale.copy,
                 callback: function (_key: string) {
                     const copyDataArr = getCopyData();
                     beforeCopy(copyDataArr);
                 },
             };
             const copyHeadersItem = {
-                name: '复制列名',
+                name: locale.copyCol,
                 callback: function (_key: string, selection: Array<any>) {
                     const copyHeaders = getCopyHeaders(selection);
                     beforeCopy([copyHeaders]);
                 },
             };
             const copyHeadersAndDataItem = {
-                name: '复制列名和值',
+                name: locale.copyAll,
                 callback: function (_key: string, selection: Array<any>) {
                     const copyDataArr = getCopyData();
                     const copyHeaders = getCopyHeaders(selection);