Repository navigation
spec: view tab labels (tabs[].label) have no translation key and no resolver — the list-page tab bar is untranslatable in every locale #5377
Description
Activity
Correction from the reporter side: this issue's central claim is wrong on
rc.2, and I verified it live rather than from schema source this time.Running HotCRM against
@objectstack/*17.0.0-rc.2 with a complete zh-CN
bundle, the account list's tab bar renders 全部客户 / 客户卡片 / 客户地图 /
企业客户 — strings that exist only under
objects.crm_account._views.*.label, reachable only by following
tabs[].view. So the console already resolves a tab's label via its referenced
view's translated label, exactly the "resolution 1" this issue listed as
unverified. The headline scenario — a translated app with an English tab bar —
does not reproduce when tabs reference views. Evidence and screenshots:
objectstack-ai/hotcrm#661 (now closable on that basis).Two narrower points from the report survive and are, I think, worth keeping
this issue open for (retitled), or splitting:- A tab with
filterbut noviewhas no translation path at all.
ViewTabSchemaallows exactly that shape; with no referenced view there is
nothing to fall back to,_tabsstill does not exist in
ObjectTranslationDataSchema, and no resolver reads tab labels. The gap is
real for that subset — it just happens that HotCRM's 59 tabs all carry
view. I18nLabelSchema's description is inaccurate ("i18n keys are
auto-generated by the framework" — none are, fortabs[].label). Worth
correcting wherever that schema is reused;AriaPropsSchema.ariaLabel
carries the same description and likely the same problem.
The visualization-switcher strings visible in the same screenshots
(Grid/Gallery) are a different component and already covered by #5084 —
not a reason to keep this issue broad.
Generated by Claude Code
- A tab with
分诊(spec 车道欠账代扫,维护者 2026-08-05 指令):挂
pm:queue,范围按报告方 08-05 更正评论收窄——正文头条场景(整条 tab 栏英文)在 rc.2 上不复现(tab 引用 view 时经_views.*.label已可翻译),派发词只框两个幸存点:①filter-only(无view)的 tab 无任何翻译路径(_tabs缺位 + 无 resolver);②I18nLabelSchema的 describe 谎称「i18n keys are auto-generated」,所有复用处(含AriaPropsSchema.ariaLabel)一并更正。落点packages/spectranslation schema / i18n-resolver / 文案。不构成认领。会话:session_01N3uGFF8teXbpgtbEJ1aYXu
Generated by Claude Code
打包建议(致 spec 座位):本单与 #5199(report / dataset 无 translator)同为 i18n translator 覆盖族,建议同一接力棒内派发,摊薄四步重建 + CI 圈的每单固定成本。背景:维护者 2026-08-06 拍板 spec 车道缩盘方案,见 #5837。
Generated by Claude Code
Release-board audit (maintainer-directed re-audit of non-board
domain:specitems, 2026-08-07): addingtarget:v17— criterion ②: filter-only view tabs (a legal authored shape) have no_tabstranslation slot or resolver, whileI18nLabelSchema's describe claims keys are auto-generated — a published-contract promise the runtime doesn't honor (scope already narrowed 08-05: view-ref tabs work on rc.2). Triage seat may veto.
Generated by Claude Code
os-project-manager commented
on Aug 8, 2026 CollaboratorMore actionsBundled into sweep card #6489 (untranslatable authoring surfaces, 2 members). Keeps
pm:queuebut is excluded from batch selection while #6489 is open — claim the sweep card, not this one; it closes viaFixeswhen that PR merges.
Generated by Claude Code
ViewTabSchema.labelis declared as anI18nLabelSchema, whose description promises"i18n keys are auto-generated by the framework". No such key exists. A view tab's label
is structurally unreachable by translation: there is no slot for it in the translation
schema and no resolver that would read one.
The result is a list-page tab bar that stays in the source language no matter how
complete a locale bundle is.
Verified against:
9f601e8(main)Downstream: objectstack-ai/hotcrm#661 — 59 tab labels across 15 objects.
Why this is now the whole remaining gap downstream
HotCRM has just finished all four of its locales (
en,zh-CN,ja-JP,es-ES):objectstack lintreports zero i18n warnings for every one of them, across fields,options, views, sections, actions, pages, navigation, dashboards and empty states.
The tab bar is the only user-visible surface still in English — and it sits at the top
of every object's list page, directly above content that is translated. A reviewer
opening the Chinese or Japanese app sees "All / Cards / Map / Enterprise / My Accounts /
Renewals / At Risk" above a fully localized grid. There is no authoring workaround: the
bundle has no key to put the translation in.
Evidence
1. The label is declared translatable.
packages/spec/src/ui/view.zod.ts:483packages/spec/src/ui/i18n.zod.ts:462. There is no key to translate it into.
ObjectTranslationDataSchema(
packages/spec/src/system/translation.zod.ts:143) is astrictObjectwhose onlygrouped members are
_views,_actionsand_sections. There is no_tabs— andbecause it is
strictObject, an author cannot add one: it is rejected, not ignored.3. Nothing resolves it.
packages/spec/src/system/i18n-resolver.tscontains notab-label resolver; the string
tabappears in that file only inside prose comments.resolveViewLabel(line 149) readsobjects.<object>._views.<view.name>.labelandnothing else.
Why this may be fixable without a schema change
Every tab in the HotCRM corpus points at a named list view via
tabs[].view, and thatview's label is translatable through
_views.<name>.label:tabs[].labelis already.optional(). If the console fell back toresolveViewLabel(referenced view)whenlabelis omitted, the whole class would closewith no schema change and no new translation key — downstream apps would just delete
their inline tab labels.
I could not confirm whether that fallback exists. The console/renderer is not in this
repository (
apps/holds onlydocs), andViewTabBarappears only in schema commentsand lint rules, never in an implementation. So this is a question for whoever owns the
renderer, not a claim.
If that route is taken, #5164 is a prerequisite to check. It reports that the
_viewskey for a default-only list container is spelled three different ways by thecomposer (
default), the extractor (list) and the lint rule (either) — so a tabfalling back to such a container would resolve to nothing. HotCRM's tabs all reference
explicitly-named
listViewskeys and so avoid that case, but a fallback design shouldnot assume every app does.
Possible resolutions, roughly in order of preference
tabs[].labelis absent. No schema change; the downstream fix is deleting inline labels. Needs the
renderer to confirm, and interacts with
_viewstranslation keys have three producers that disagree on the spelling — a default-onlylistcontainer can never resolve #5164._tabsgroup toObjectTranslationDataSchemaplus aresolveTabLabelhelper, mirroring
_views/_sections. Explicit and unambiguous, but adds a key forsomething the
viewreference arguably already addresses. Note that tabs may alsocarry a
filterand noviewat all, in which case there is no view to fall back to— which is an argument for this option over (1).
tabs[].labelas untranslatable and change it fromI18nLabelSchematoa plain
z.string(). Least work, but the tab bar stays monolingual — hard to defendfor a list page's primary navigation.
Whichever way it goes, the
I18nLabelSchemadescription on this field is inaccuratetoday and worth correcting either way: no key is auto-generated for it. The same
description is attached to
AriaPropsSchema.ariaLabel, which is worth auditing for thesame problem.
Reproduction
tabsarray where each tab has alabeland aview.objects.<object>._views.<name>.labelforevery referenced view.
bar above it stays in the source language.
Related
_viewstranslation keys have three producers that disagree on the spelling — a default-onlylistcontainer can never resolve #5164 —_viewskey spelling disagreement; a prerequisite for resolution (1).AddressFieldsub-labels and placeholders are hardcoded English literals — an address field is untranslatable on any non-English console #5083 —AddressFieldsub-labels are hardcoded English literals. Same class of defect(a surface with no reachable translation key) on a different component.