Repository navigation
feat(studio): a Chinese display name derives its identifier by pinyin at every Studio create door - #29734
Conversation
Every Studio create door that derives a machine name from a display name now romanises Chinese words to toneless pinyin first (lazy pinyin-pro chunk, Intl.Segmenter word boundaries), then applies its existing sanitizer, so prefix, __c and taken-name rules are unchanged. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QsR2jTMu2EmYV84fwNrBXw
Shared rule (words, polyphones, ü, kana left alone, Segmenter missing), chunk-load failure and late landing, and a zh-CN case per door; pins that asserted a Chinese name derives nothing now use a Japanese one. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QsR2jTMu2EmYV84fwNrBXw
…lands The object, report and dataset designers refilled an empty Name from the Label on every render, so a person who cleared the derived Name to type their own got the pinyin back. A shared useWhenRomanizerLands hook runs the fill only on the render where the dictionary landed; the picklist options editor uses it too. The permission-set banner pin types a Japanese label, since a Chinese one now derives a Name. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QsR2jTMu2EmYV84fwNrBXw
…-tlcgw9 Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QsR2jTMu2EmYV84fwNrBXw
…-tlcgw9 Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QsR2jTMu2EmYV84fwNrBXw
|
domain:ui#4 · zhuangjianguo · session_01QsR2jR7ZFkpqmm4U8S1f9y 席位核对 · ACCEPT · 2026-11-03T03:23ZHead-sha:
Generated by Claude Code |
Requested by Steedos · project thread
Fixes #29690
Clause-②: no
Metadata-protocol: none
Claim: 6593397218 · amendments 6593439786, 6593495761
维护者速读
维修中心→weixiu_zhongxin,客户等级→kehu_dengji。生成的标识照常显示、可改。pinyin-pro是按需加载的独立分包,首次遇到汉字才下载;加载失败时退回原来的“无法生成,请手填”。常驻包只多 0.9 KB(预算内)。回滚即还原本 PR,无数据迁移。romanizeHan.ts(共享规则与加载状态);StudioDesignSurface.tsx两行(添加字段预览名与实际创建名一致);PackageFormDialog.tsx(软件包 ID 与命名空间)。cd ui && pnpm exec vitest run packages/app-shell/src/views/metadata-admin/romanizeHan.test.ts,预期 9 条全绿(含多音字银行→yinhang、行动→xingdong)。What changes
One shared derivation,
ui/packages/app-shell/src/views/metadata-admin/romanizeHan.ts, sits in front of each door's existing sanitizer. Latin text is untouched; each Chinese word becomes its toneless pinyin, then the door applies the rule it always applied (toFieldNameLoose,toFieldNameOrEmpty,slugify, or the package id'stoIdSegment). So the namespace prefix, the__csuffix of a customization pair and the taken-name hint are unchanged; they now seeweixiu_zhongxinwhere they used to see an empty string.com.<org>.weixiu-zhongxin, namespaceweixiu_zhongxin); the new-item dialog; Add field, where the popover's preview and the host's created name both go through the helper, so the name previewed is the name created; the generic create form (createDerive.ts); New view; the object, report and dataset designers' Name; a fresh field's API name in the field inspector; and a picklist option's value. That last one was a silent loss: a Chinese option label derived an empty value and the row was never saved.Intl.Segmenter('zh', { granularity: 'word' }), andpinyin-proreads a polyphone by its word (银行→yinhang,行动→xingdong).üis writtenv(绿色→lvse). WithoutIntl.Segmenter, each character's reading is joined by_(ke_hu_deng_ji).romanizerPending). When it lands, a door whose identifier still follows the name fills it in without another keystroke (useHanRomanizer/useWhenRomanizerLands). The fill runs once, on the render where the dictionary landed, so a person who clears the identifier to type their own is never refilled. If the chunk cannot be fetched, the load settles as failed, oneconsole.warnsays so, and every door falls back to its "not derived" line and a hand-typed identifier, as before this PR.Bundle choice. The client derives the pinyin itself, from
pinyin-proloaded as a lazy chunk. It is the library the server's pinyin search plugin already uses and is already in the lockfile, and it reads polyphones by word. I rejected a server route because it would add a REST route for a create-time preview, andplugin-pinyin-searchruns only behindOS_SEARCH_PINYIN_ENABLED. I rejected the collator-sort libraries because they read polyphones wrong.pnpm --dir ui check:eager-closure:1c1a5d40The last row's extra 0.5 KB is main's own change in
vendor-objectstack, which went from 573.1 to 573.6 KB. The ceiling and baseline are untouched, and headroom is 337.3 KB. The dictionary chunk isassets/esm-Cst8rBvH.js: 286.6 KB raw, 141.7 KB gzipped, and lazy. The helper itself, about 0.9 KB, is in the eager closure becausePackageFormDialogis eager. The seat accepted this on the card thread.Tests
New:
romanizeHan.test.tsweixiu_zhongxinandkehu_dengjithrough every door sanitizer, plus the polyphone pair,lvse, mixed维修Center 2号→weixiu_center_2_hao, and kana unchanged.Intl.Segmenterabsent:ke_hu_deng_jiandyin_hang.romanizeHan.loadFailure.test.tsxCreateItemDialogshows its "not derived" line, and a hand-typed id submits.romanizeHan.lands-29690.test.tsxCreateItemDialogstays empty and quiet with Create off while loading, then showsweixiu_zhongxinwith Create on.createDerive.romanizerLands-29690.test.tsxkehu_dengjiwith nothing underivable.ReportDefaultInspector.romanizerLands-29690.test.tsxCreateViewDialog.pinyinName-29690.test.tsx客户列表→kehu_liebiao, and the name is editable.Extended with a zh-CN case each:
CreateItemDialog.notDerived-13389: the namespace prefix givesrepairs_weixiu_zhongxin.PackageFormDialog.idDerive-11792: orgacmegivescom.acme.weixiu-zhongxinand namespaceweixiu_zhongxinin the posted manifest; the id stays editable.DataPillar.addFieldPopover-12516: the previewkehu_dengjiequals the created field; a second客户等级gets the taken-name hint.DataPillar.baseObjectExtension-28575: the previewkehu_dengji__cequals the extension field saved.ResourceEditPage.underivableName-28232Report…/DatasetDefaultInspector.labelLeavesNameEmpty-12789ObjectDefaultInspectorObjectFieldInspector.apiNameSyncObjectFieldInspector.optionLabelFirst-27521:进行中/已完成→jinxing_zhong/yi_wanchengsaved, and the field parses.Kana samples replace the Chinese ones in
PackageFormDialog.derivedFields-12512,PackageFormDialog.nameOnlyFirstStep-27833andResourceEditPage.identifierIssueI18n-28369.Ablations went through
scripts/ablation-replace.mjs. Each one went red and was restored to HEAD:romanizeHanreturns its inputAcceptance notes
Verification
All runs were under
os-verify-lock.Affected tests, type-check, lint
turbo-affected app-shell test files: 308 files in 6 batches.pnpm exec turbo run type-check --filter=@object-ui/app-shell: 65 of 65 tasks pass.eslinton the changed files: 0 errors.Gates
node scripts/pm/dispatch-gates.mjs --commandsderived 57 commands on this diff, and--ranreconciled all 57. 56 exit 0.check:dual-build-cjs-loadsexits 3, because it needs every workspace package built; it is left to CI. The exit codes are in the os-dev report on the card.Generated by Claude Code