resolveViewLabel (packages/spec/src/system/i18n-resolver.ts:149) cannot resolve any view authored through the normal path. Every view label in a running console falls back to its English literal, no matter what the translation bundle contains. Found while translating a customer-facing app; the app's twelve _views translation blocks turned out to have never been read.
Filed unassigned — recording the finding, not claiming it.
Two independent mismatches, either one sufficient
function viewObjectName(view: ViewLike): string | undefined {
return view.objectName ?? view.data?.object; // :141
}
const objectName = viewObjectName(view);
if (!bundle || !objectName) return fallback; // :156
const candidate = data?.objects?.[objectName]?._views?.[view.name]?.label; // :159
This is what GET /api/v1/meta/view?object=crm_account actually serves:
{
"name": "crm_account.account_gallery",
"object": "crm_account",
"viewKind": "list",
"label": "Account Cards",
"config": {
"name": "account_gallery",
"label": "Account Cards",
"data": { "provider": "object", "object": "crm_account" }
}
}
-
The object never resolves. objectName is absent — the field is object. data is absent — it is nested at config.data. So viewObjectName returns undefined and line 156 returns the fallback before any lookup happens.
-
The key would be wrong even if it did. The lookup uses view.name, which the served document namespaces to crm_account.account_gallery. Translations are keyed on the bare name — objects.crm_account._views.account_gallery.label — which is also what config.name carries.
Fixing only the first leaves every lookup missing; fixing only the second never runs.
Measured, not inferred
In an app with objects.crm_account._views.all_accounts.label = '全部客户' present in the served zh-CN bundle, the console renders All Accounts. The unit tests at i18n-resolver.test.ts:127 pass because they construct ViewLike objects by hand with objectName and a bare name — a shape the runtime never produces.
Impact
Every list view's switcher tab, on every object, in every locale. On a Chinese-only deployment this is the most visible remaining English on the screen: it sits across the top of every list page, above data that is otherwise fully translated.
There is no workaround at the app layer other than authoring the labels in Chinese directly in src/views, which hard-codes one language into metadata and defeats the other three locales.
Worth deciding together with
report and dataset have no translator at all — no entry in METADATA_DOCUMENT_TRANSLATORS, no key in TranslationDataSchema, and defineStack strips a reports: block while tsc rejects it as an excess property (TS2353). Dataset dimension and measure labels are what a dataset-bound dashboard widget renders its table column headers from, so those are permanently English too.
One clue suggesting the dataset case may not need a new surface: a dimension whose name matches a real field name on the bound object already renders the translated field label. In the same dashboard, current_grade (dimension name = field name) shows Chinese while account_name (dimension name ≠ field name name) shows Customer. If the resolver fell back to the field label whenever a dimension names one, most of these would resolve with no new translation surface at all.
resolveViewLabel(packages/spec/src/system/i18n-resolver.ts:149) cannot resolve any view authored through the normal path. Every view label in a running console falls back to its English literal, no matter what the translation bundle contains. Found while translating a customer-facing app; the app's twelve_viewstranslation blocks turned out to have never been read.Filed unassigned — recording the finding, not claiming it.
Two independent mismatches, either one sufficient
This is what
GET /api/v1/meta/view?object=crm_accountactually serves:{ "name": "crm_account.account_gallery", "object": "crm_account", "viewKind": "list", "label": "Account Cards", "config": { "name": "account_gallery", "label": "Account Cards", "data": { "provider": "object", "object": "crm_account" } } }The object never resolves.
objectNameis absent — the field isobject.datais absent — it is nested atconfig.data. SoviewObjectNamereturnsundefinedand line 156 returns the fallback before any lookup happens.The key would be wrong even if it did. The lookup uses
view.name, which the served document namespaces tocrm_account.account_gallery. Translations are keyed on the bare name —objects.crm_account._views.account_gallery.label— which is also whatconfig.namecarries.Fixing only the first leaves every lookup missing; fixing only the second never runs.
Measured, not inferred
In an app with
objects.crm_account._views.all_accounts.label = '全部客户'present in the servedzh-CNbundle, the console rendersAll Accounts. The unit tests ati18n-resolver.test.ts:127pass because they constructViewLikeobjects by hand withobjectNameand a barename— a shape the runtime never produces.Impact
Every list view's switcher tab, on every object, in every locale. On a Chinese-only deployment this is the most visible remaining English on the screen: it sits across the top of every list page, above data that is otherwise fully translated.
There is no workaround at the app layer other than authoring the labels in Chinese directly in
src/views, which hard-codes one language into metadata and defeats the other three locales.Worth deciding together with
reportanddatasethave no translator at all — no entry inMETADATA_DOCUMENT_TRANSLATORS, no key inTranslationDataSchema, anddefineStackstrips areports:block whiletscrejects it as an excess property (TS2353). Dataset dimension and measure labels are what a dataset-bound dashboard widget renders its table column headers from, so those are permanently English too.One clue suggesting the dataset case may not need a new surface: a dimension whose
namematches a real field name on the bound object already renders the translated field label. In the same dashboard,current_grade(dimension name = field name) shows Chinese whileaccount_name(dimension name ≠ field namename) showsCustomer. If the resolver fell back to the field label whenever a dimension names one, most of these would resolve with no new translation surface at all.