Skip to content

Commit 8cd8f0d

Browse files
committed
fix(plugin-timeline): gantt bucket labels and the Items default speak the session language (#4520)
objectui#4513 routed every `Intl` call in the timeline renderer through `useDisplayLocale()`, so a zh session renders `2026年8月` on the month axis. Three sibling strings in the same renderer never went through `Intl` at all and stayed English beside it: the `week` header (`Week 1`), the `quarter` header (`Q3 2026`), and the gantt row-label default (`Items`). These are a translation concern, not a locale-resolver one — a locale TAG formats a date, only a TRANSLATION spells a word. All three now resolve through the package's existing channel (`useTimelineTranslation` / `TIMELINE_DEFAULT_TRANSLATIONS`, already used for `timeline.bucket.*`) under three new keys carried by all ten locale packs: `timeline.scale.week`, `timeline.scale.quarter`, `timeline.gantt.rowLabel`. The numbers ride the channel's own `{{hole}}` parameters rather than concatenation, because word order belongs to the translation: zh puts the year first (`2026年第3季度`), which no `Q${q} ${year}` template can produce. `generateTimeScaleHeaders` is a pure exported function and cannot host a hook, so `t` is threaded in as an optional 5th parameter on the seam #4513 opened for `locale`, defaulting to the package's own defaults table. English output is byte-identical and existing 3-/4-argument call sites are unaffected. #4513's suite deliberately pinned `Week 1` / `Q3 2026` staying English to keep that card's scope honest; this card moves exactly those two expectations. The year-only `2026` header is a bare number and stays. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017Qqyix2QcnpUC9XeYVDzx3
1 parent 01c9188 commit 8cd8f0d

16 files changed

Lines changed: 498 additions & 12 deletions
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
'@object-ui/plugin-timeline': minor
3+
'@object-ui/i18n': minor
4+
---
5+
6+
The timeline's gantt bucket labels and its row-label default speak the session language
7+
8+
objectui#4513 routed every `Intl` call in the timeline renderer through `useDisplayLocale()`, so a Chinese session renders `2026年8月` on the month axis and `2026年8月11日` on item dates. Three sibling strings in the same renderer never went through `Intl` at all and stayed English on that same Chinese axis: the `week` header (`Week 1`), the `quarter` header (`Q3 2026`), and the gantt row-label column default (`Items`). The half-fixed state was the visible one — a Chinese date axis with English bucket labels beside it.
9+
10+
They are a translation concern rather than a locale-resolver one, and that distinction is the fix: a locale TAG formats a date, only a TRANSLATION spells a word. All three now resolve through the package's existing channel — `useTimelineTranslation` / `TIMELINE_DEFAULT_TRANSLATIONS`, the `createSafeTranslation` factory `ObjectTimeline` already uses for `timeline.bucket.*` — under three new keys carried by all ten locale packs: `timeline.scale.week`, `timeline.scale.quarter`, `timeline.gantt.rowLabel`.
11+
12+
The week number and the quarter/year ride the channel's own `{{hole}}` parameters rather than being concatenated, because the word order belongs to the translation: Chinese puts the year first (`2026年第3季度`), which no `Q${q} ${year}` template can produce at all. Only the row-label DEFAULT moved — an author who writes `rowLabel` still supplies their own string, and the `year` scale stays a bare `String(getFullYear())` with no vocabulary in it to translate.
13+
14+
English output is byte-identical to the retired literals: the `en` pack values are the same two templates the code used to interpolate by hand. `generateTimeScaleHeaders` is a pure exported function and cannot host a hook, so the translate fn is threaded in as an optional fifth parameter on the seam #4513 opened for `locale`, defaulting to the package's own defaults table — the same lookup the channel serves with no `I18nProvider` mounted. Existing three- and four-argument call sites are unaffected.
15+
16+
One consequence is worth stating because it looks like a bug and is not: dates and vocabulary resolve through different channels on purpose. `useDisplayLocale()` puts the tenant's regional default first (how this organization writes dates), while `t` follows the UI language (what this user reads). A tenant configured `en` whose user reads Chinese chrome therefore sees `Aug 2026` beside `第 1 周` — the same split `timeline.bucket.*` has always had.

packages/i18n/src/locales/ar.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -643,6 +643,13 @@ const ar = {
643643
noDate: "بدون تاريخ",
644644
unassigned: "غير معين",
645645
},
646+
scale: {
647+
week: "الأسبوع {{n}}",
648+
quarter: "الربع {{quarter}} {{year}}",
649+
},
650+
gantt: {
651+
rowLabel: "العناصر",
652+
},
646653
},
647654
gantt: {
648655
viewMode: {

packages/i18n/src/locales/de.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,13 @@ const de = {
639639
noDate: "Kein Datum",
640640
unassigned: "Nicht zugewiesen",
641641
},
642+
scale: {
643+
week: "Woche {{n}}",
644+
quarter: "Q{{quarter}} {{year}}",
645+
},
646+
gantt: {
647+
rowLabel: "Elemente",
648+
},
642649
},
643650
gantt: {
644651
viewMode: {

packages/i18n/src/locales/en.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -688,6 +688,13 @@ const en = {
688688
noDate: 'No date',
689689
unassigned: 'Unassigned',
690690
},
691+
scale: {
692+
week: 'Week {{n}}',
693+
quarter: 'Q{{quarter}} {{year}}',
694+
},
695+
gantt: {
696+
rowLabel: 'Items',
697+
},
691698
},
692699
gantt: {
693700
column: {

packages/i18n/src/locales/es.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -643,6 +643,13 @@ const es = {
643643
noDate: "Sin fecha",
644644
unassigned: "Sin asignar",
645645
},
646+
scale: {
647+
week: "Semana {{n}}",
648+
quarter: "T{{quarter}} {{year}}",
649+
},
650+
gantt: {
651+
rowLabel: "Elementos",
652+
},
646653
},
647654
gantt: {
648655
viewMode: {

packages/i18n/src/locales/fr.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,13 @@ const fr = {
639639
noDate: "Sans date",
640640
unassigned: "Non attribué",
641641
},
642+
scale: {
643+
week: "Semaine {{n}}",
644+
quarter: "T{{quarter}} {{year}}",
645+
},
646+
gantt: {
647+
rowLabel: "Éléments",
648+
},
642649
},
643650
gantt: {
644651
viewMode: {

packages/i18n/src/locales/ja.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,13 @@ const ja = {
639639
noDate: "日付なし",
640640
unassigned: "未割当",
641641
},
642+
scale: {
643+
week: "第{{n}}週",
644+
quarter: "{{year}}年第{{quarter}}四半期",
645+
},
646+
gantt: {
647+
rowLabel: "項目",
648+
},
642649
},
643650
gantt: {
644651
viewMode: {

packages/i18n/src/locales/ko.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,13 @@ const ko = {
639639
noDate: "날짜 없음",
640640
unassigned: "미할당",
641641
},
642+
scale: {
643+
week: "{{n}}주차",
644+
quarter: "{{year}}년 {{quarter}}분기",
645+
},
646+
gantt: {
647+
rowLabel: "항목",
648+
},
642649
},
643650
gantt: {
644651
viewMode: {

packages/i18n/src/locales/pt.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -638,6 +638,13 @@ const pt = {
638638
noDate: "Sem data",
639639
unassigned: "Não atribuído",
640640
},
641+
scale: {
642+
week: "Semana {{n}}",
643+
quarter: "T{{quarter}} {{year}}",
644+
},
645+
gantt: {
646+
rowLabel: "Itens",
647+
},
641648
},
642649
gantt: {
643650
viewMode: {

packages/i18n/src/locales/ru.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,13 @@ const ru = {
645645
noDate: "Без даты",
646646
unassigned: "Не назначено",
647647
},
648+
scale: {
649+
week: "Неделя {{n}}",
650+
quarter: "{{quarter}} кв. {{year}}",
651+
},
652+
gantt: {
653+
rowLabel: "Элементы",
654+
},
648655
},
649656
gantt: {
650657
viewMode: {

0 commit comments

Comments
 (0)