Ant Design ConfigProvider 国际化(locale)实战:运行时切换语言与本地化支持组件全景
导读
在 Ant Design 中,大部分组件内置的文案默认是英文(如 Pagination 的上一页/下一页、DatePicker 的占位符、Table 的"暂无数据"等)。要在一套应用中为这些组件提供本地化支持,官方推荐的唯一入口就是 ConfigProvider 的 locale 属性。本文基于仓库中 locale 演示代码 及其配套说明(locale.md),讲解"哪些组件需要国际化支持、如何在演示与真实项目中切换语言、locale 数据从注入到消费的底层链路",并结合 locale 模块 源码与 国际化官方指南,给出可直接复制运行的完整方案。读完本文,你将掌握 ConfigProvider locale 的正确用法、dayjs 语言包同步的必要性,以及 70+ 语言包的结构与扩展方式。
一、locale 演示要解决的核心问题
配置演示(locale.md)的定位非常明确:
此处列出 Ant Design 中需要国际化支持的组件,你可以在演示里切换语言。
它说明两件事:其一,Ant Design 内存在一批内置文案需要跟随语言包变化的组件;其二,这些组件被集中放进一个演示页,用来直观展示 ConfigProvider 的 locale 在运行时切换语言的完整效果。
与它配套的 locale.tsx 演示页集中渲染了如下组件:Pagination、Select、DatePicker、TimePicker、RangePicker、Modal(含 Modal.info/Modal.confirm 静态方法)、Popconfirm、Transfer、Calendar、Form、Input、InputNumber、Table、Upload、Tour、QRCode、Image、Divider、Button。它们几乎全部出现在 Locale 接口 所声明的语言包条目中(Pagination、DatePicker、TimePicker、Calendar、Table、Modal、Tour、Popconfirm、Transfer、Select、Upload、Form、QRCode、global 等),也就是说演示页与语言包数据结构一一对应——这正是"需要国际化支持的组件"清单的直接来源。
二、演示页解剖:如何在同一页面内切换语言
整个演示由两个 React 组件构成:内部 Page(负责渲染需要本地化的业务 UI)和外部 App(负责持有并切换语言状态、包裹 ConfigProvider)。
2.1 语言状态与切换逻辑
const App: React.FC = () => {
const [locale, setLocale] = useState<Locale>(enUS);
const changeLocale = (e: RadioChangeEvent) => {
const localeValue = e.target.value;
setLocale(localeValue);
if (!localeValue) {
dayjs.locale('en');
} else {
dayjs.locale('zh-cn');
}
};
return (
<>
<div style={{ marginBottom: 16 }}>
<Radio.Group value={locale} onChange={changeLocale}>
<Radio.Button key="en" value={enUS}>English</Radio.Button>
<Radio.Button key="cn" value={zhCN}>中文</Radio.Button>
</Radio.Group>
</div>
<ConfigProvider locale={locale}>
<Page />
</ConfigProvider>
</>
);
};
关键点有三:
- 语言包即组件文案快照:
enUS、zhCN是antd/locale/en_US与antd/locale/zh_CN两个完整语言包对象,直接作为Radio的 value,选中哪个 Radio,就把哪个对象赋给localestate。类型约束ConfigProviderProps['locale']可复用官方导出的Locale类型。 ConfigProvider只需包裹一次:改变localestate 会触发ConfigProvider重新渲染,进而让整个子树共享新的语言上下文,演示页里的Pagination、Calendar、Modal等文案会即时刷新。- 必须同步 dayjs 的语言:antd 内置的 date 类组件(DatePicker、TimePicker、Calendar、RangePicker)基于 dayjs 实现。antd 语言包只负责 antd 自身的文案,dayjs 的周起点、月份、季度等日期语义需要单独配置。演示中:
import 'dayjs/locale/zh-cn';
dayjs.locale('en');
切到英文时 dayjs.locale('en'),切到中文时 dayjs.locale('zh-cn')。这正是官方 国际化指南 反复强调的 "for date-picker i18n, import dayjs/locale/xxx"。
2.2 Page 覆盖的"本地化组件全家桶"
Page 内部按块渲染了大量组件,便于肉眼验证切换效果,例如:
Pagination defaultCurrent={1} total={50} showSizeChanger:验证每页条数选择器的文案(zh_CN 为"条/页");Select、DatePicker、TimePicker、RangePicker:验证占位符与面板操作按钮;Modal(受控弹窗)、Modal.info、Modal.confirm:验证确认框的"确定/取消"按钮文案;Popconfirm、Transfer(含showSearch)、Calendar fullscreen={false}:验证气泡确认与穿梭框搜索等文案;Form(含必填校验规则)与InputNumber:验证校验报错文案来自Form.defaultValidateMessages;Table(含filters)、Upload(picture-card 三种状态)、Tour(三步引导)、QRCode status="expired":验证空数据、上传状态、刷新等语义化文案。
一句话总结该演示的结构:外层一个 ConfigProvider 提供 locale,内部一屏组件负责"验收",这是生产项目"语言切换 + 全局文案一致性"的最小可运行模板。
三、语言包从注入到消费的底层链路
了解演示写法之后,值得深入到 locale 模块 与 ConfigProvider 实现 中,看一份语言对象到底是如何"流"到每个组件里的。
3.1 Locale 数据结构的顶层形状
components/locale/index.tsx#L21-L69 定义了 Locale 接口:除 locale 标识字段外,每个可本地化组件对应一个 xxxLocale 字段。以 zh_CN 语言包 为例,其文件开头即组合了来自子模块的语言片段:
import Pagination from '@rc-component/pagination/locale/zh_CN';
import Calendar from '../calendar/locale/zh_CN';
import DatePicker from '../date-picker/locale/zh_CN';
import TimePicker from '../time-picker/locale/zh_CN';
随后是 global(placeholder/close/sortable/show/hide)、Table(filterTitle/emptyText/selectAll 等)、Form(含 defaultValidateMessages 与校验模板 '${label}不是一个有效的${type}')、Modal、Popconfirm、Transfer、QRCode 等完整条目。由此可见每个语言包都是按组件维度组织的"文案树",这也解释了为什么 en_US.ts 被当作新增语言包的基底模板。
3.2 ConfigProvider 内部:剥离 default 并交给 LocaleProvider
在 ConfigProvider 的实现 中,locale 处理有两步值得注意:
- 兼容 ES Module 场景的
default解包(index.tsx#L465-L475):当传入的对象带有default.locale属性时(例如import zhCN from 'antd/locale/zh_CN'被某些打包器二次封装),会自动取出.default,避免语言不生效; - 将最终 locale 交给内部
LocaleProvider(即旧版本独立存在的LocaleProvider组件),并传入_ANT_MARK__内部标记(index.tsx#L680-L682)。
LocaleProvider 本身(locale/index.tsx#L78-L104)做了三件事:
- 通过
LocaleContext.Provider把{ ...locale, exist: true }写入 React Context(context 定义见 locale/context.ts),子树组件从useLocale/useContext读取; - 在非生产环境校验
_ANT_MARK__,若没有标记则提示 "LocaleProvideris deprecated. Please uselocalewithConfigProvider"——在组件树里直接使用LocaleProvider已被废弃,应以ConfigProvider locale={...}为准; - 调用
changeConfirmLocale(locale?.Modal)并把清除函数作为副作用,保证Modal.confirm/Modal.info等静态方法能读到正确的 Modal 文案。
3.3 语言默认值与消费侧
ConfigProvider 默认引入 defaultLocale(en_US),因此在没有任何配置时,antd 组件文案显示为英文——这正是 国际化指南 开头所说"antd 目前的默认文案是英文"的代码级出处。具体组件消费端则通过 locale/useLocale.ts 之类的工具把"ConfigProvider 上下文语言"与"组件级 locale 覆盖"合并后渲染。整体数据流可概括为:
antd/locale/zh_CN ──> ConfigProvider locale ──> LocaleProvider
└─> LocaleContext.Provider ──> 各组件 useLocale/useContext ──> 渲染本地化文案
└─> changeConfirmLocale ──> Modal/Message/Notification 静态方法
四、把演示方案落地到真实项目
演示的核心思路可以直接移植到任何 React 应用。一个更接近真实场景的最小骨架如下(对应 docs/react/i18n.zh-CN.md 的推荐写法):
import zhCN from 'antd/locale/zh_CN';
import enUS from 'antd/locale/en_US';
// dayjs 需要单独处理,否则日期组件的月份等文案不会跟着切换
import dayjs from 'dayjs';
import 'dayjs/locale/zh-cn';
const App = () => (
<ConfigProvider locale={zhCN}>
<YourApp />
</ConfigProvider>
);
在需要"用户可切换语言"的产品中,参考 locale 演示的做法即可:
- 用一个全局状态(如 Context/状态库)保存当前语言标识;
- 通过 map 得到对应语言包对象与 dayjs locale 名,语言包切换时同步调用
dayjs.locale(...); - 外层只保留一个
ConfigProvider(可嵌套合并其他配置如theme、direction),让整棵组件树共享同一 locale; - 若用到
Modal.confirm/message等静态方法,推荐使用App组件包裹(app 目录)以消费全局配置;仅在 v5 使用ConfigProvider.config()会影响静态方法(见 ConfigProvider 文档)。
另外注意:locale 针对的是组件内置文案。若你的业务文案需要国际化,需要结合 react-intl / i18next 等方案另行处理,ConfigProvider 只负责 antd 组件层,二者互不冲突。
五、可用的语言包范围与扩展方法
Ant Design 在 components/locale/ 下为每种语言提供独立文件,文件名即 语言_地区 形式(如 zh_CN.ts、en_US.ts、ja_JP.ts),按 国际化指南 的清单目前覆盖 70+ 种语言,典型包括:
- 中文系:
zh_CN、zh_HK、zh_TW; - 日韩系:
ja_JP、ko_KR; - 欧美系:
en_US、en_GB、fr_FR、de_DE、es_ES、pt_BR等; - 中东/南亚系:
ar_EG、fa_IR、he_IL、hi_IN、th_TH等。
导入方式统一为 import zhCN from 'antd/locale/zh_CN',需配合组件库构建工具支持子路径导出。若缺少目标语言,官方推荐以 en_US.ts 为模板新建语言包并向仓库提交 PR;仓库内 locale 测试 同时覆盖了"切换各语言后组件文案渲染正确"的回归验证,新增语言时需要同步补充对应 dayjs locale 的 import 与测试快照。
六、验证手段:测试与文档交叉佐证
本仓库为 locale 行为提供了多层验证:
- components/config-provider/tests/locale.test.tsx:围绕 ConfigProvider 的 locale 属性验证中文/英文文案切换、Modal 静态方法文案等;
- components/locale/tests/index.test.tsx:遍历加载全部语言包并逐一断言组件渲染文案(文件开头即为每种语言注册对应 dayjs locale,印证了"语言包与 dayjs 必须配对使用");
- components/locale/useLocale.ts:组件侧读取 locale 的统一入口。
想快速验证本文所有结论,可直接把 locale.tsx 演示 拷贝进项目,在 ConfigProvider 外层套一个 App 组件即可获得完整可用、可切换中英文的组件文案预览页。
总结
围绕 locale 演示 的这条线索可以看到:antd 的国际化并非魔法,而是一套"语言包(components/locale)→ ConfigProvider 注入 → LocaleContext 分发 → 各组件消费 + Modal 静态方法同步"的清晰机制。掌握这套机制后,你既能像演示页那样在运行时一键切换语言,也能在接入 dayjs、扩展语言包、排查"切换后日期组件没变"等常见问题时快速定位根因。核心口诀只有一句:语言包交给 ConfigProvider,日期语义交给 dayjs,两者同步切换,组件文案自然跟着变。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00