Uh oh!
There was an error while loading. Please reload this page.
fix(fields): 注册路径的全屏长文本对话框接上 i18n(#3404) - #3405
Merged
Merged
Conversation
…log (#3404) `FullscreenFieldEditor` — the expand button and dialog `TextAreaField` and `RichTextField` render under `mobile.fullscreenLongText` — carried four English literals: the toggle's accessible name, the `Edit text` title fallback, `Cancel` and `Done`. No translation was missing: `form.fullscreen.*` and `common.cancel` have shipped in all ten locale packs since #3272 translated the built-in branch; this path never consumed them. Inside one form a zh session saw the built-in branch's translated footer next to this path's English one. All four now consume those EXISTING keys — no new keys, no locale-pack change — plus the sr-only `form.fullscreen.description` the built-in branch already carries, so the dialog has an `aria-describedby` instead of none. Copy resolves through `useFieldTranslation()` (`createSafeTranslation`), as the built-in branch does, not bare `useObjectTranslation`. Measured with no provider mounted, the bare hook returns raw keys (`common.cancel` -> "common.cancel") and drops the `{{label}}` interpolation — strictly worse than the literals. The safe hook's English defaults are byte-identical to those literals, so provider-less hosts render what they did before. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt
The latest updates on your projects. Learn more about Vercel for GitHub. |
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
yinlianghui
marked this pull request as ready for review
August 5, 2026 20:19
Uh oh!
There was an error while loading. Please reload this page.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes#3404
问题
packages/fields/src/widgets/FullscreenFieldEditor.tsx四处英文字面量:展开按钮的可访问名(Edit ${label ?? 'text'} fullscreen)、标题兜底Edit text、Cancel、Done。键一个都不缺 ——
form.fullscreen.*与common.cancel自 #3272 给内置分支做国际化起就在十个语言包里齐全,只是这条路径从没消费。可达性也不是理论上的:mobile.fullscreenLongText打开后ObjectForm给每个长文本字段盖mobile_fullscreen,于是同一张表单内,内置分支渲染的字段显示「取消 / 完成」,注册 widget 渲染的显示 Cancel / Done。改动
四处全部改为消费既有键,零新增键、十个语言包一行未动。另补上内置分支早已有的 sr-only
form.fullscreen.description,详见下。关键实现选择:走
useFieldTranslation()而不是 issue 正文提到的裸useObjectTranslation。 这一点是实测决定的,不是偏好。本包 widget 会被独立/嵌入宿主以及本包绝大多数测试不带I18nProvider裸渲染,而在改动前的树上实测裸 hook 在无 provider 时返回的是原始键:{{label}}插值也整个塌掉 —— 比它要替换的英文字面量更差。useFieldTranslation(createSafeTranslation)正是内置分支自 #3272 起用的形状,其英文兜底与原字面量逐字节相同,因此无 provider 的渲染结果完全不变。相应地,英文兜底项加在了本包既有的FIELD_DEFAULTS(useFieldTranslation.ts)里 —— 那是代码内的英文兜底表,不是语言包,仍是零新增 i18n 键;common.cancel本就在表内,直接复用。「顺带观察」的 DialogDescription:补了,但理由与 issue 猜测的不同
issue 猜测可能触发 Radix 的 missing-Description 警告。实测该警告不存在:锁定的
@radix-ui/react-dialog@1.1.23整个文件里一个console.*调用都没有,上游已移除该警告,baseline 跑也确实没有任何告警输出。补它的真实理由是另外两条:Radix 仅在存在 Description 时才设置
aria-describedby(descriptionPresent ? descriptionId : undefined),所以改动前这条路径的对话框根本没有可访问描述,而逐像素相同的内置对话框有;且form.fullscreen.description在此路径上是个无消费者的键 —— 与本 issue 主体是同一处漂移。同文件、零新键。测试
新增两个文件,合计 14 例,textarea 与 richtext 两个 widget 各覆盖:
__tests__/FullscreenFieldEditor.i18n.test.tsx—— en 正向(与旧字面量逐字节相同,证明 en 是 no-op)、zh/ja 正向 + 英文字面量反向断言(只做正向断言的话,重新内联的字面量挨着翻译过的兄弟节点照样能过);ja 是因为 toggle 名是插值的、两个包把通用名词放在句子两端,只测 zh 会蒙混过关。另含 label 插值、aria-describedby、以及提交/取消仍然接线正常。__tests__/FullscreenFieldEditor.no-provider.test.tsx—— 无 provider 的那条腿,含 Commandment #-1 的无 CJK 断言。为什么无 provider 那几例必须单独成文件(这是本 PR 返工过的一处): 它们最初写在 i18n 文件里。反向验证(把
useFieldTranslation换回裸useObjectTranslation,预期变红)时它们依然全绿,而同一次实验正确地把RichTextField.mobileFullscreen.test.tsx弄红了。原因是I18nProvider会调用initReactI18next,把实例装成 react-i18next 的全局默认;同文件内只要有一例挂过 provider,就再也没有「无 provider」状态可观测 —— 那几例是靠读泄漏的全局实例而绿的,属于「因为什么都没发生而通过」的假绿。拆成独立文件后,同样的替换实验让它们如实变红(aria-label="form.fullscreen.toggle"),这才算真的钉住。同样的拆分理由见TagsField.placeholder.no-provider.test.tsx。反向验证方向
Tests 6 failed | 2 passed,失败的正是 zh/ja 各例(Received: aria-label="Edit text fullscreen");通过的 2 例是两个en用例 —— 它们改动前后都绿,因为字面量与 en 包逐字节相同。这一点如实记录:en 用例是 no-op 保护,不是缺陷复现器。aria-label="form.fullscreen.toggle"原始键,其中一例是既有的RichTextField.mobileFullscreen.test.tsx(它按'Edit Release notes fullscreen'查按钮)。命令与结果
从仓根跑(包内跑会假绿 / 路径过滤被吞,见 #3288/#3378),并以文件名核对确实执行:
按消费半径而非编辑包扫了 fixture:
packages/plugin-form/src/__tests__/ObjectForm.mobileFullscreen.test.tsx在packages/fields之外也消费这个组件,已纳入上面的运行范围;packages/i18n的语言包 parity 套件一并跑过,确认没有包漂移。范围
严格限定在
FullscreenFieldEditor.tsx+ 测试 + changeset(patch),外加useFieldTranslation.ts里的英文兜底项 —— 那是让本次改动不产生回归所必需的最小外扩(理由见上),且不属于裁定禁止的 form.tsx / 语言包 / TextAreaField / RichTextField 任何一项。未碰 form.tsx,未碰任何 locale 文件,未改两个宿主 widget。Generated by Claude Code