Skip to content

Commit d535eaf

Browse files
committed
wip(i18n): translate the newly addressable global-filter keys; fix test typing
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016N6xmWt5hYm94ffVEwGH8x
1 parent d2fc4e8 commit d535eaf

7 files changed

Lines changed: 64 additions & 9 deletions

File tree

docs/audits/2026-07-unknown-key-strictness-ledger.counts.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,4 +264,4 @@ directory rather than per file.
264264
| `kernel/` | 260 |
265265
| `qa/` | 6 |
266266
| `shared/` | 20 |
267-
| `system/` | 350 |
267+
| `system/` | 351 |

examples/app-showcase/src/system/translations/index.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,20 @@ export const ShowcaseTranslationBundle = {
323323
kpi_paid_rate: { title: 'Paid Rate' },
324324
table_rate_by_status: { title: 'Paid Rate by Status' },
325325
},
326+
// The filter bar drawn above the widgets — declared surface since
327+
// `dashboards.<name>.globalFilters` (#16772), keyed by the filter's
328+
// `name`; static options keyed by their `value`.
329+
globalFilters: {
330+
region: { label: 'Region', options: { amer: 'AMER', emea: 'EMEA', apac: 'APAC' } },
331+
},
332+
},
333+
showcase_ops_dashboard: {
334+
globalFilters: {
335+
task_status: {
336+
label: 'Task Status',
337+
options: { backlog: 'Backlog', todo: 'To Do', in_progress: 'In Progress', in_review: 'In Review', done: 'Done' },
338+
},
339+
},
326340
},
327341
},
328342
},
@@ -973,6 +987,20 @@ export const ShowcaseTranslationBundle = {
973987
kpi_paid_rate: { title: '已付比例' },
974988
table_rate_by_status: { title: '各状态已付比例' },
975989
},
990+
// Born under the ratchet with `dashboards.<name>.globalFilters`
991+
// (#16772): the filter label and its static option labels are
992+
// declared surface now, so they are translated at birth.
993+
globalFilters: {
994+
region: { label: '区域', options: { amer: '美洲', emea: '欧洲、中东和非洲', apac: '亚太' } },
995+
},
996+
},
997+
showcase_ops_dashboard: {
998+
globalFilters: {
999+
task_status: {
1000+
label: '任务状态',
1001+
options: { backlog: '待办池', todo: '待处理', in_progress: '进行中', in_review: '审核中', done: '已完成' },
1002+
},
1003+
},
9761004
},
9771005
},
9781006
// Page component copy became declared surface with `pages.<name>.components`

packages/platform-objects/src/apps/translations/en.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,12 @@ export const en: TranslationData = {
229229
description: 'Event volume grouped by action (login, logout, config, …)',
230230
},
231231
},
232+
// The date-range bar above the widgets — addressable since
233+
// `dashboards.<name>.globalFilters` (#16772), keyed by the filter's
234+
// `field` because it authors no `name`.
235+
globalFilters: {
236+
created_at: { label: 'Date Range' },
237+
},
232238
},
233239
},
234240

packages/platform-objects/src/apps/translations/es-ES.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,12 @@ export const esES: TranslationData = {
154154
widget_events_by_user: { title: 'Eventos por Usuario', description: 'Distribución de actividad entre usuarios' },
155155
widget_recent_events: { title: 'Volumen de Eventos por Acción', description: 'Volumen de eventos agrupado por acción (inicio de sesión, cierre de sesión, configuración, …)' },
156156
},
157+
// The date-range bar above the widgets — addressable since
158+
// `dashboards.<name>.globalFilters` (#16772), keyed by the filter's
159+
// `field` because it authors no `name`.
160+
globalFilters: {
161+
created_at: { label: 'Rango de fechas' },
162+
},
157163
},
158164
},
159165

packages/platform-objects/src/apps/translations/ja-JP.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,12 @@ export const jaJP: TranslationData = {
154154
widget_events_by_user: { title: 'ユーザー別イベント', description: 'ユーザー別アクティビティ分布' },
155155
widget_recent_events: { title: 'アクション別イベント件数', description: 'アクション別にグループ化されたイベント件数(ログイン、ログアウト、構成など)' },
156156
},
157+
// The date-range bar above the widgets — addressable since
158+
// `dashboards.<name>.globalFilters` (#16772), keyed by the filter's
159+
// `field` because it authors no `name`.
160+
globalFilters: {
161+
created_at: { label: '日付範囲' },
162+
},
157163
},
158164
},
159165

packages/platform-objects/src/apps/translations/zh-CN.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,12 @@ export const zhCN: TranslationData = {
164164
widget_events_by_user: { title: '按用户分布的事件', description: '用户活动分布' },
165165
widget_recent_events: { title: '按操作统计的事件量', description: '按操作分组的事件量(登录、登出、配置等)' },
166166
},
167+
// The date-range bar above the widgets — addressable since
168+
// `dashboards.<name>.globalFilters` (#16772), keyed by the filter's
169+
// `field` because it authors no `name`.
170+
globalFilters: {
171+
created_at: { label: '日期范围' },
172+
},
167173
},
168174
},
169175

packages/spec/src/system/i18n-resolver.test.ts

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1175,12 +1175,14 @@ describe('translateDashboard — global filters (#16772)', () => {
11751175
});
11761176

11771177
it('translates the filter label and its static option labels, keyed by `name`', () => {
1178-
const out = translateDashboard(dashboard(), bundle, { locale: 'zh-CN' });
1178+
// The chain is the deployment's DECLARED one (#14882): `en` is consulted
1179+
// because the caller names it, never by default.
1180+
const out = translateDashboard(dashboard(), bundle, { locale: 'zh-CN', fallbackChain: ['en'] });
11791181
expect(out.globalFilters![0].label).toBe('申请部门');
11801182
expect(out.globalFilters![0].options).toEqual([
11811183
{ value: 'legal', label: '法务' },
11821184
{ value: 'sales', label: '销售' },
1183-
// Resolved key by key along the locale chain — `ops` comes from `en`.
1185+
// Resolved key by key along the declared chain — `ops` comes from `en`.
11841186
{ value: 'ops', label: 'Operations' },
11851187
// No entry anywhere on the chain: authored label kept.
11861188
{ value: 'hr', label: 'HR' },
@@ -1211,7 +1213,7 @@ describe('translateDashboard — global filters (#16772)', () => {
12111213
expect(out.globalFilters![2]).toBe(doc.globalFilters[2]);
12121214
// The input is never mutated.
12131215
expect(doc.globalFilters[0].label).toBe('Requesting Department');
1214-
expect(doc.globalFilters[0].options[0].label).toBe('Legal');
1216+
expect(doc.globalFilters[0].options?.[0]?.label).toBe('Legal');
12151217
});
12161218

12171219
it('CONTROL: leaves `globalFilters` off the copy when nothing resolved, and invents none on a dashboard without filters', () => {
@@ -2318,11 +2320,12 @@ describe('translatePage — slotted page roots and tab panels (#16772)', () => {
23182320
};
23192321

23202322
it('addresses a slotted page — the walk count is non-zero and every authored id is visited once', () => {
2321-
// Measured here, on this fixture: 9 components authored (1 header, 1
2322-
// path, 1 details, 1 tabs, 3 related lists in panels, 1 card, 1 nested
2323-
// related list); the `body` control is not a visit. The card's own
2324-
// number came from one app and one console build and is not restated.
2325-
expect(count(contractPage())).toBe(9);
2323+
// Measured here, on this fixture: 8 components authored (1 header, 1
2324+
// path, 1 details, 1 tabs, 2 related lists directly in panels, 1 card in
2325+
// a panel, 1 related list nested in that card); the `body` control is
2326+
// not a visit. The card's own number came from one app and one console
2327+
// build and is not restated.
2328+
expect(count(contractPage())).toBe(8);
23262329
const ids: string[] = [];
23272330
walkAddressedPageComponents(contractPage(), (c, { id, addressed }) => {
23282331
if (addressed) ids.push(id as string);

0 commit comments

Comments
 (0)