react-admin `<TranslatableInputs>` 多语言表单输入组件完整指南:分语言编辑、校验与编程式赋值
react-adminTranslatableInputs多语言表单输入组件完整指南分语言编辑、校验与编程式赋值【免费下载链接】react-adminA frontend Framework for single-page applications on top of REST/GraphQL APIs, using TypeScript, React and Material Design项目地址: https://gitcode.com/gh_mirrors/re/react-adminTranslatableInputs是 react-admin 提供的多语言表单输入容器组件它允许开发者把一组每个字段对应多语言值的输入如name.en、name.fr组织成带语言选项卡的编辑界面。本文基于当前仓库 docs/TranslatableInputs.md 展开结合ra-ui-materialui与ra-core的源码实现系统讲解其数据模型、全部 Props、自定义语言选择器、校验联动、以及如何配合react-hook-form的setValue编程式修改各语言值。一、组件定位与适用场景在多语言业务系统如电商商品、CMS 内容、新闻稿中同一个字段往往需要保存多个语言的翻译文本。react-admin 对此有两种展示形态只读展示使用TranslatableFields分语言展示字段值编辑输入使用本文的TranslatableInputs让用户在一个表单内为每种语言分别填写值。TranslatableInputs不要求提供source属性它本身只是容器但它要求至少一个带source的子输入组件同时必须通过locales属性声明要展示的语言。其源码定义位于 packages/ra-ui-materialui/src/input/TranslatableInputs.tsx底层逻辑语言切换、记录转换由ra-core的useTranslatable提供。组件期望的字段值结构如下每个字段都是语言码 → 文本的对象{ id: 1234, name: { en: White trousers, fr: Pantalon blanc, }, description: { en: Slim fit trousers for every day use, fr: Pantalon ajusté pour un usage quotidien, } }二、基本用法将需要多语言编辑的输入组件作为TranslatableInputs的子节点传入并通过locales声明语言TranslatableInputs locales{[en, fr]} TextInput sourcename / RichTextInput sourcedescription / /TranslatableInputs页面渲染效果上方是一个 Material UI 选项卡条每个选项卡标签是语言码如en、fr下方是对应当前选中语言的一组输入框。切换选项卡时react-admin 会为该语言的每个子输入生成形如name.en、name.fr的动态source从而实现一套字段结构、多语言独立编辑。从源码来看TranslatableInputs的核心渲染流程TranslatableInputs.tsx#L72-L114是调用useTranslatable({ defaultLocale, locales })获取语言切换上下文通过TranslatableContextProvider注入该上下文渲染语言选择器默认是TranslatableInputsTabs即 Material UI 的 Tabs遍历locales为每个语言渲染一个TranslatableInputsTabContent把同一组子输入包进各语言的容器中。每个TranslatableInputsTabContentpackages/ra-ui-materialui/src/input/TranslatableInputsTabContent.tsx会做两件关键的事通过SourceContextProvider注入一个getSource: source ${source}.${locale}的上下文让子输入自动挂上语言后缀通过RecordContextProvider注入一份当前语言的值记录由getRecordForLocale从原始记录中抽取因为普通输入组件并不知道语言的存在它们只从RecordContext取当前字段值。这里getRecordForLocale的实现值得注意packages/ra-core/src/i18n/useTranslatable.ts#L55-L74它递归遍历记录的所有路径getRecordPaths支持嵌套对象与数组把形如title.fr的值提升为title从而构造出仅含指定语言值的记录。这意味着TranslatableInputs也适用于嵌套结构如数组内对象的翻译字段。三、Props 总览TranslatableInputs的 Props 定义于 TranslatableInputs.tsx#L116-L125接口继承UseTranslatableOptions完整参数如下Prop必填类型默认值说明locales必填Arraystring-语言码数组顺序即选项卡顺序defaultLocale可选string跟随用户语言默认展示的语言fullWidth可选booleantrue设为false时输入组不撑满表单宽度groupKey可选string-用于可访问性的唯一标识同页多个实例时必填selector可选ReactElementMaterial UI Tabs自定义语言选择器元素StackProps可选object{}透传给内部 MUI Stack 的属性sx可选SxProps-Material UI 样式快捷方式其余内部还支持className、marginnone \| normal \| dense。从源码可见组件支持 MUI 主题级定制其样式类名为RaTranslatableInputs包含root与fullWidth两个规则可通过 MUIcomponents覆盖见 TranslatableInputs.tsx#L146-L162。四、defaultLocale默认展示语言react-admin 默认取当前用户的语言useLocaleState中的localeFromUI作为defaultLocale这一点在 useTranslatable.ts#L26-L28 中可以看到const [localeFromUI] useLocaleState(); const { defaultLocale localeFromUI, locales } options;若希望某个表单固定以特定语言打开用defaultLocale覆盖TranslatableInputs locales{[en, fr]} defaultLocalefr TextInput sourcename / RichTextInput sourcedescription / /TranslatableInputs源码中还有一个细节selectedLocale为 falsy 时例如defaultLocale为空字符串会回退到enuseTranslatable.ts#L33。五、fullWidth宽度控制默认情况下TranslatableInputs组会撑满表单宽度——源码根节点样式为flexGrow: 1且启用fullWidth时追加width: 100%TranslatableInputs.tsx#L136-L144。如需禁用TranslatableInputs locales{[en, fr]} fullWidth{false} TextInput sourcetitle / TextInput sourcedescription / /TranslatableInputs六、groupKey同页多实例的可访问性标识TranslatableInputs内部依赖一组固定的 DOM id 建立选项卡 ↔ 内容面板的关联如translatable-header-${groupKey}${locale}、translatable-content-${groupKey}${locale}见 TranslatableInputsTabContent.tsx#L68-L76。如果同一页面出现多个TranslatableInputs这些 id 会冲突因此必须为每个实例提供唯一的groupKeyTranslatableInputs locales{[en, fr]} groupKeyessential-fields TextInput sourcename / RichTextInput sourcedescription / /TranslatableInputsgroupKey同时会被拼入FormGroupContext的名称${groupKey}${locale}确保各语言分组的表单上下文互不干扰。七、locales语言列表与选项卡标签locales传入字符串数组每个字符串既是语言码也会成为输入值的键后缀。数组顺序决定了选项卡从左到右的展示顺序TranslatableInputs locales{[en, fr]} TextInput sourcename / RichTextInput sourcedescription / /TranslatableInputs选项卡默认以语言码作为标签。如果希望显示人类可读的语言名如 English 而非 en可以使用翻译键格式为ra.locales.[locale_code]例如ra.locales.en、ra.locales.fr。以ra-i18n-polyglot或自定义翻译包在对应语言文件中配置这些键即可。八、selector自定义语言选择器默认选择器是 Material UI Tabs实现见 TranslatableInputsTabs.tsx一个AppBar容器内嵌Tabs每个选项卡的值是语言码。你可以通过selector属性替换成任意自定义元素例如一个原生select下拉框const Selector () { const { locales, selectLocale, selectedLocale, } useTranslatableContext(); const handleChange event { selectLocale(event.target.value); }; return ( select aria-labelSelect the locale onChange{handleChange} value{selectedLocale} {locales.map(locale ( option key{locale} value{locale} // This allows to correctly link the containers for each locale to their labels id{translatable-header-${locale}} {locale} /option ))} /select ); }; TranslatableInputs record{record} resourceproducts locales{[en, fr]} selector{Selector /} TextInput sourcename / RichTextInput sourcedescription / /TranslatableInputs自定义选择器通过useTranslatableContext获取上下文可用值包括locales语言码数组selectedLocale当前选中语言selectLocale(locale)切换语言的方法getRecordForLocale(record, locale)抽取指定语言记录的工具函数。注意自定义selector若用原生元素需要自己保证选项卡 ↔ 面板的id/aria-labelledby关联上例中translatable-header-${locale}正是面板aria-labelledby所引用的 id。useTranslatableContext在脱离TranslatableContextProvider使用时即组件不在TranslatableInputs内部会抛出错误这一点由 useTranslatableContext.ts#L39-L43 保证。九、StackProps控制内部布局每个语言的输入内容都被包裹在一个 MUIStack中StackProps会原样透传{...StackProps}见 TranslatableInputs.tsx#L100-L110。默认方向为垂直堆叠设置direction: row可以让输入并排显示TranslatableInputs locales{[en, fr]} StackProps{{ direction: row }} TextInput sourcetitle / TextInput sourcedescription sx{{ marginLeft: 2 }} / /TranslatableInputsStackProps支持 MUI Stack 的全部属性包括spacing、direction、alignItems、justifyContent等适合在空间紧张的表单中做紧凑排版。十、sx自定义样式TranslatableInputs根节点同样支持sx可用于设置边框、背景、间距等样式TranslatableInputs locales{[en, fr]} sx{{ border: solid 1px red }} TextInput sourcetitle / TextInput sourcedescription / /TranslatableInputssx会被应用到根容器源码中由styled(div)创建的Root同时仍可通过 MUI 主题的RaTranslatableInputs.styleOverrides做全局覆盖。十一、校验错误联动到选项卡TranslatableInputs内的任何输入组件都可以照常使用 react-admin 的校验器。当某个语言的输入出现校验错误时对应语言的选项卡标签会被标记为错误状态标红高亮TranslatableInputs locales{[en, fr]} TextInput sourcename validate{[required()]} / RichTextInput sourcedescription validate{[maxLength(100)]} / /TranslatableInputs这一行为在仓库测试 packages/ra-ui-materialui/src/input/TranslatableInputs.spec.tsx 中有明确覆盖测试通过断言tabs[1].classList.contains(RaTranslatableInputsTab-error)来验证含错误输入的选项卡是否正确获得错误样式类同时测试也验证了未选中语言的面板会附加hidden样式类display: none实现隐藏切换。实现机制上每个语言的选项卡由TranslatableInputsTab渲染它会感知所在语言的FormGroupContext状态校验错误在表单层面按语言分组记录因此可以精确反映到具体语言选项卡上。十二、编程式修改多语言值useSourceContextsetValueTranslatableInputs的表单值依然由react-hook-form管理因此可以直接调用其setValue方法修改某个输入的值。但难点在于子输入在表单中注册的name是按语言动态生成的例如description.en直接写死字段名无法适配。react-admin 为此提供了SourceContextpackages/ra-core/src/core/SourceContext.tsx通过useSourceContext钩子可以在任意层级拿到getSource(source)函数它会返回该输入在当前上下文中的真实source。在TranslatableInputs内这个函数就是字段名 当前语言后缀的拼接器见 TranslatableInputsTabContent.tsx#L41-L56。源码细节SourceContext默认值是一个恒等函数getSource: source source因此在不处于任何特殊上下文时使用也不会报错而TranslatableInputsTabContent提供的getSource在source为空时会抛出Children of TranslatableInputs must have a source从实现层面强制了子输入必须有source的约束。下面示例展示了如何利用getSource拿到各语言的动态name再用setValue把title的值预填到descriptionimport { TranslatableInputs, TextInput, useSourceContext } from react-admin; import { useFormContext } from react-hook-form; import { Button } from mui/material; const PrefillWithTitleButton () { const sourceContext useSourceContext(); const { setValue, getValues } useFormContext(); const onClick () { setValue( // sourceContext.getSource(description) will for instance return // description.en sourceContext.getSource(description), getValues(sourceContext.getSource(title)) ); }; return ( Button onClick{onClick} sizesmall sx{{ maxWidth: 140 }} Prefill with title /Button ); }; const MyInputs () ( TranslatableInputs locales{[en, fr]} TextInput sourcetitle / TextInput sourcedescription helperText{false} / PrefillWithTitleButton / /TranslatableInputs );关键点useSourceContext()可在TranslatableInputs的任何子组件中使用拿到的是当前语言上下文下的getSource由于按钮同样位于TranslatableInputsTabContent内部getSource(title)与getSource(description)会自动带上当前选中语言的后缀如title.fr、description.fr因此预填逻辑天然跟随用户正在编辑的语言若在TranslatableInputs之外使用useSourceContext得到的是恒等上下文getSource直接返回原字段名符合普通表单的行为。十三、小结TranslatableInputs是 react-admin 处理多语言编辑场景的标准方案数据模型字段值为语言码 → 文本的对象locales定义语言集合使用要点子输入必须有source多实例必须给groupKey默认语言可被defaultLocale覆盖交互定制selector可完全替换默认 Tabs 选择器StackProps/sx/MUI 主题覆盖可灵活调整布局与样式校验各语言独立校验错误自动标记到对应选项卡编程式控制配合useSourceContext().getSource与react-hook-form的setValue可在任意语言上下文中精准读写字段值。相关源码与测试可作为继续深入研究的入口TranslatableInputs.tsx、TranslatableInputsTabContent.tsx、TranslatableInputsTabs.tsx、useTranslatable.ts、SourceContext.tsx、TranslatableInputs.spec.tsx。只读展示场景可对照参考TranslatableFields。【免费下载链接】react-adminA frontend Framework for single-page applications on top of REST/GraphQL APIs, using TypeScript, React and Material Design项目地址: https://gitcode.com/gh_mirrors/re/react-admin创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

TiXL DampPeakDecay 算子深度解析:峰值保持与指数衰减的实时浮点信号处理

TiXL DampPeakDecay 算子深度解析:峰值保持与指数衰减的实时浮点信号处理

TiXL DampPeakDecay 算子深度解析:峰值保持与指数衰减的实时浮点信号处理 【免费下载链接】t3 TiXL is an open source software to create realtime motion graphics. 项目地址: https://gitcode.com/GitHub_Trending/t3/t3 导读 DampPeakDecay 是 TiXL 算…

2026/9/21 15:29:36 阅读更多 →
Trigger.dev 托管 Webhooks 控制台前端开发指南:本地环境搭建、数据流水线与四大界面设计实战

Trigger.dev 托管 Webhooks 控制台前端开发指南:本地环境搭建、数据流水线与四大界面设计实战

AI Agent后端任务调度开发工具可观测性AI 应用 【免费下载链接】trigger.dev Trigger.dev – build and deploy durable AI agents and workflows 项目地址: https://gitcode.com/gh_mirrors/tr/trigger.dev 点击查看 免费下载 本篇技术指南以 Trigger.dev 仓库中&…

2026/9/21 15:29:36 阅读更多 →
Sails 框架中 Waterline 查询实例的 `.toPromise()` 方法:原理、用法与最佳实践

Sails 框架中 Waterline 查询实例的 `.toPromise()` 方法:原理、用法与最佳实践

Sails 框架中 Waterline 查询实例的 .toPromise() 方法:原理、用法与最佳实践 【免费下载链接】sails Realtime MVC Framework for Node.js 项目地址: https://gitcode.com/gh_mirrors/sa/sails 导读 .toPromise() 是 Sails(基于 Node.js 的实时…

2026/9/21 15:29:36 阅读更多 →

最新新闻

SEO优化见效慢?5个立竿见影的技巧与7个致命错误

SEO优化见效慢?5个立竿见影的技巧与7个致命错误

1. 为什么你的SEO优化总是见效慢?做SEO最让人抓狂的就是:明明按照教程操作了,排名却迟迟不见提升。我见过太多人把时间浪费在错误的优化策略上,比如疯狂堆砌关键词、购买垃圾外链,结果要么被算法惩罚,要么效…

2026/9/21 15:56:01 阅读更多 →
Neo4j Cypher Shell 交互式集成测试:用 Expect 脚本与 Docker 驱动端到端验证

Neo4j Cypher Shell 交互式集成测试:用 Expect 脚本与 Docker 驱动端到端验证

数据库图数据库后端 【免费下载链接】neo4j Graphs for Everyone 项目地址: https://gitcode.com/gh_mirrors/ne/neo4j 点击查看 免费下载 Cypher Shell 是 Neo4j 自带的命令行客户端,它的交互行为(提示符、历史命令、CtrlC 中断、空闲超时、…

2026/9/21 15:56:01 阅读更多 →
CC Switch 接 TaoToken:三秒切到 GLM 5.3 Flash

CC Switch 接 TaoToken:三秒切到 GLM 5.3 Flash

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/21 15:56:01 阅读更多 →
glibc 太低连不上 Cursor 远程?让走 TaoToken 的 Codex 照着 patchelf 那步查

glibc 太低连不上 Cursor 远程?让走 TaoToken 的 Codex 照着 patchelf 那步查

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/21 15:56:01 阅读更多 →
VxWorks+CODESYS软PLC实时控制实战:稳准快的工业自动化方案

VxWorks+CODESYS软PLC实时控制实战:稳准快的工业自动化方案

1. 项目概述:为什么工业现场需要在VxWorks上跑CODESYS Runtime?在工业自动化一线干了十多年,我经手过上百台PLC、IPC和边缘控制器的部署调试。很多人一听到“VxWorks”就下意识觉得这是航天军工才用的“老古董”,而“CODESYS”则是…

2026/9/21 15:56:01 阅读更多 →
Nim 后端集成全指南:C / C++ / Objective-C / JavaScript 多目标编译与双向互操作

Nim 后端集成全指南:C / C++ / Objective-C / JavaScript 多目标编译与双向互操作

Nim 后端集成全指南:C / C / Objective-C / JavaScript 多目标编译与双向互操作 【免费下载链接】Nim Nim is a statically typed compiled systems programming language. It combines successful concepts from mature languages like Python, Ada and Modula. It…

2026/9/21 15:55:00 阅读更多 →

日新闻

agents-generator 决策矩阵全解析:从项目检测到 AGENTS.md 规则生成的 16 步判定流程

agents-generator 决策矩阵全解析:从项目检测到 AGENTS.md 规则生成的 16 步判定流程

agents-generator 决策矩阵全解析:从项目检测到 AGENTS.md 规则生成的 16 步判定流程 【免费下载链接】agentic-awesome-skills AAS Core is the local, agent-first control plane for complete catalog discovery, agent-owned selection, stack validation, and …

2026/9/21 0:00:01 阅读更多 →
gin-vue-admin 前端工具函数全景指南:src/utils 复用规范与源码级解析

gin-vue-admin 前端工具函数全景指南:src/utils 复用规范与源码级解析

gin-vue-admin 前端工具函数全景指南:src/utils 复用规范与源码级解析 【免费下载链接】gin-vue-admin 🚀ViteVue3Gin拥有AI辅助的基础开发平台,企业级业务AI开发解决方案,内置mcp辅助服务,内置skills管理,…

2026/9/21 0:00:01 阅读更多 →
Wox 全功能插件开发实战指南:基于 Python / Node.js 宿主与 WebSocket 的持久化插件体系

Wox 全功能插件开发实战指南:基于 Python / Node.js 宿主与 WebSocket 的持久化插件体系

桌面应用AI 应用插件系统 【免费下载链接】Wox A cross-platform launcher that simply works 项目地址: https://gitcode.com/gh_mirrors/wo/Wox 点击查看 免费下载 全功能插件(Full-featured Plugin)是 Wox 三类插件实现方式中能力最完整的…

2026/9/21 0:00:01 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/21 3:13:20 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/21 2:19:36 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/21 4:51:05 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/21 15:36:51 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/21 15:36:51 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/19 23:35:34 阅读更多 →