Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .changeset/7149-activity-timeline-remaining-literals.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
---
'@object-ui/plugin-detail': patch
'@object-ui/i18n': patch
---

`ActivityTimeline` speaks the session locale — the other 18 literals
(objectui#7149).

objectui#7142 gave this component its first `t()` call (the empty-state title)
and filed the sweep that found the rest. Until now a zh activity tab read
`"Activity(0)暂无活动记录"`: one translated string in a component that was
otherwise entirely English.

All 18 now resolve from the ten packs, in three groups:

- **Relative timestamps and the card title** (`just now`, `{{count}}m/h/d ago`,
`Activity`) — these render on *every* activity tab. All five were a pure
lookup swap: the `en` pack value was already byte-identical to the literal,
and the sibling `RecordActivityTimeline` already used the same keys.
- **The `formatFieldChange` sentences** — assembled in code, so they needed new
keys *with* interpolation holes rather than a lookup. Same reachability as the
timestamps: they render for any entry whose optional `description` is absent.
The quotes live inside each pack's value, so every locale punctuates its own
way (de `„…“`, zh `“…”`, ja `「…」`, fr/ru `«…»`).
- **The six filter chips and the chip group's accessible name** — reachable only
through the published export, since no host in this repo passes `filterable`.

Ten new `detail.*` keys across all ten packs (no inline `defaultValue` —
objectui#3517), mirrored byte-for-byte into `DETAIL_DEFAULT_TRANSLATIONS` so a
provider-less host still reads English rather than a raw key.

One deliberate English copy change: the chip group's `aria-label` was
`"Activity type filter"` and now resolves `detail.filterActivity`
(`"Filter activity"`) — the key `RecordActivityTimeline` already uses for the
accessible name of its own activity filter, so one control does not carry two
names across two components.

Also drops the unused `Filter` import (a pre-existing eslint warning).
20 changes: 13 additions & 7 deletions packages/i18n/src/__tests__/de-quote-pairing-3876.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -268,8 +268,13 @@ describe('objectui#3876 — de pack closes „ with “ and not with a straight
// 55 once objectui#6655 added `timeline.unsupported.objectBoundGantt`, the
// object-bound timeline's refusal of `variant: gantt`, which names the
// refused variant — „gantt“, a literal span, because the quoted thing is an
// authoring value the author typed rather than data the runtime filled in.
expect(okSpans, 'correctly paired spans').toBe(55);
// authoring value the author typed rather than data the runtime filled in,
// 58 once objectui#7149 gave `ActivityTimeline`'s assembled sentences pack
// keys: `detail.activityFieldChanged` quotes the OLD and NEW field values
// („{{old}}“ / „{{new}}“, two spans in one value, like `navigationSync.
// renamedPage` above) and `detail.activityStatusChanged` the new status
// („{{value}}“) — three interpolated spans, all runtime data.
expect(okSpans, 'correctly paired spans').toBe(58);
});

it('keeps the count identity that replaces the card’s count(„) === count(“)', () => {
Expand All@@ -289,11 +294,12 @@ describe('objectui#3876 — de pack closes „ with “ and not with a straight
// 53 / 53 / 0 after objectui#5232 added
// `console.objectView.viewConfigPermissionDenied`; 54 / 54 / 0 after
// objectui#6301 added `packagedAutomation.cloneCreated`; 55 / 55 / 0 after
// objectui#6655 added `timeline.unsupported.objectBoundGantt`. `rdq` staying
// at 0 is the load-bearing half: each new value added a MATCHED „…“ pair,
// not a stray closer that would have made `close === open` true for the
// wrong reason.
expect({ open, close, rdq }).toEqual({ open: 55, close: 55, rdq: 0 });
// objectui#6655 added `timeline.unsupported.objectBoundGantt`; 58 / 58 / 0
// after objectui#7149 added the two quoted `ActivityTimeline` sentences
// (three spans between them). `rdq` staying at 0 is the load-bearing half:
// each new value added a MATCHED „…“ pair, not a stray closer that would
// have made `close === open` true for the wrong reason.
expect({ open, close, rdq }).toEqual({ open: 58, close: 58, rdq: 0 });
// The durable shape: every „ closed by a “, every surplus “ an English
// opener answered by a ”. Survived translating the two English values.
expect(close).toBe(open + rdq);
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/ar.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -960,6 +960,19 @@ const ar = {
tasksOnly: "المهام فقط",
leaveCommentPlaceholder: "اترك تعليقاً… (Ctrl+Enter للإرسال)",
noActivity: "لا يوجد نشاط مسجل",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'الكل',
createsFilter: 'عمليات الإنشاء',
deletesFilter: 'عمليات الحذف',
statusChangesFilter: 'تغييرات الحالة',
activityEmptyValue: '(فارغ)',
activityFieldChanged: 'غيّر {{field}} من "{{old}}" إلى "{{new}}"',
activityCreated: 'أنشأ هذا السجل',
activityDeleted: 'حذف هذا السجل',
activityStatusChanged: 'غيّر الحالة إلى "{{value}}"',
activityUpdated: 'حدّث السجل',
loadMore: "تحميل المزيد",
edited: "(معدل)",
via: "عبر {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/de.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -954,6 +954,19 @@ const de = {
tasksOnly: "Nur Aufgaben",
leaveCommentPlaceholder: "Kommentar hinterlassen… (Strg+Enter zum Senden)",
noActivity: "Keine Aktivitäten aufgezeichnet",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'Alle',
createsFilter: 'Erstellungen',
deletesFilter: 'Löschungen',
statusChangesFilter: 'Statusänderungen',
activityEmptyValue: '(leer)',
activityFieldChanged: '{{field}} von „{{old}}“ zu „{{new}}“ geändert',
activityCreated: 'Diesen Datensatz erstellt',
activityDeleted: 'Diesen Datensatz gelöscht',
activityStatusChanged: 'Status zu „{{value}}“ geändert',
activityUpdated: 'Datensatz aktualisiert',
loadMore: "Mehr laden",
edited: "(bearbeitet)",
via: "über {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/en.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -1168,6 +1168,19 @@ const en = {
tasksOnly: 'Tasks Only',
leaveCommentPlaceholder: 'Leave a comment… (Ctrl+Enter to submit)',
noActivity: 'No activity recorded',
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'All',
createsFilter: 'Creates',
deletesFilter: 'Deletes',
statusChangesFilter: 'Status Changes',
activityEmptyValue: '(empty)',
activityFieldChanged: 'Changed {{field}} from "{{old}}" to "{{new}}"',
activityCreated: 'Created this record',
activityDeleted: 'Deleted this record',
activityStatusChanged: 'Changed status to "{{value}}"',
activityUpdated: 'Updated record',
loadMore: 'Load more',
edited: '(edited)',
via: 'via {{source}}',
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/es.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -958,6 +958,19 @@ const es = {
tasksOnly: "Solo tareas",
leaveCommentPlaceholder: "Deja un comentario… (Ctrl+Enter para enviar)",
noActivity: "Sin actividad registrada",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'Todo',
createsFilter: 'Creaciones',
deletesFilter: 'Eliminaciones',
statusChangesFilter: 'Cambios de estado',
activityEmptyValue: '(vacío)',
activityFieldChanged: 'Cambió {{field}} de "{{old}}" a "{{new}}"',
activityCreated: 'Creó este registro',
activityDeleted: 'Eliminó este registro',
activityStatusChanged: 'Cambió el estado a "{{value}}"',
activityUpdated: 'Actualizó el registro',
loadMore: "Cargar más",
edited: "(editado)",
via: "vía {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/fr.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -956,6 +956,19 @@ const fr = {
tasksOnly: "Tâches uniquement",
leaveCommentPlaceholder: "Laisser un commentaire… (Ctrl+Entrée pour envoyer)",
noActivity: "Aucune activité enregistrée",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'Tout',
createsFilter: 'Créations',
deletesFilter: 'Suppressions',
statusChangesFilter: 'Changements de statut',
activityEmptyValue: '(vide)',
activityFieldChanged: '{{field}} modifié de « {{old}} » à « {{new}} »',
activityCreated: 'A créé cet enregistrement',
activityDeleted: 'A supprimé cet enregistrement',
activityStatusChanged: 'A changé le statut en « {{value}} »',
activityUpdated: 'A mis à jour l\'enregistrement',
loadMore: "Charger plus",
edited: "(modifié)",
via: "via {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/ja.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -965,6 +965,19 @@ const ja = {
tasksOnly: "タスクのみ",
leaveCommentPlaceholder: "コメントを入力… (Ctrl+Enterで送信)",
noActivity: "アクティビティの記録なし",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'すべて',
createsFilter: '作成',
deletesFilter: '削除',
statusChangesFilter: 'ステータス変更',
activityEmptyValue: '(空)',
activityFieldChanged: '{{field}} を「{{old}}」から「{{new}}」に変更しました',
activityCreated: 'このレコードを作成しました',
activityDeleted: 'このレコードを削除しました',
activityStatusChanged: 'ステータスを「{{value}}」に変更しました',
activityUpdated: 'レコードを更新しました',
loadMore: "さらに読み込む",
edited: "(編集済み)",
via: "{{source}} 経由",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/ko.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -954,6 +954,19 @@ const ko = {
tasksOnly: "작업만",
leaveCommentPlaceholder: "댓글 남기기… (Ctrl+Enter로 제출)",
noActivity: "기록된 활동 없음",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: '전체',
createsFilter: '생성',
deletesFilter: '삭제',
statusChangesFilter: '상태 변경',
activityEmptyValue: '(비어 있음)',
activityFieldChanged: '{{field}}을(를) "{{old}}"에서 "{{new}}"(으)로 변경했습니다',
activityCreated: '이 레코드를 만들었습니다',
activityDeleted: '이 레코드를 삭제했습니다',
activityStatusChanged: '상태를 "{{value}}"(으)로 변경했습니다',
activityUpdated: '레코드를 업데이트했습니다',
loadMore: "더 보기",
edited: "(수정됨)",
via: "{{source}} 통해",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/pt.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -955,6 +955,19 @@ const pt = {
tasksOnly: "Apenas tarefas",
leaveCommentPlaceholder: "Deixar um comentário… (Ctrl+Enter para enviar)",
noActivity: "Nenhuma atividade registrada",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'Tudo',
createsFilter: 'Criações',
deletesFilter: 'Exclusões',
statusChangesFilter: 'Alterações de status',
activityEmptyValue: '(vazio)',
activityFieldChanged: 'Alterou {{field}} de "{{old}}" para "{{new}}"',
activityCreated: 'Criou este registro',
activityDeleted: 'Excluiu este registro',
activityStatusChanged: 'Alterou o status para "{{value}}"',
activityUpdated: 'Atualizou o registro',
loadMore: "Carregar mais",
edited: "(editado)",
via: "via {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/ru.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -973,6 +973,19 @@ const ru = {
tasksOnly: "Только задачи",
leaveCommentPlaceholder: "Оставить комментарий… (Ctrl+Enter для отправки)",
noActivity: "Нет зарегистрированной активности",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'Все',
createsFilter: 'Создания',
deletesFilter: 'Удаления',
statusChangesFilter: 'Изменения статуса',
activityEmptyValue: '(пусто)',
activityFieldChanged: 'Изменено поле {{field}} с «{{old}}» на «{{new}}»',
activityCreated: 'Создал эту запись',
activityDeleted: 'Удалил эту запись',
activityStatusChanged: 'Изменил статус на «{{value}}»',
activityUpdated: 'Обновил запись',
loadMore: "Загрузить ещё",
edited: "(изменено)",
via: "через {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/zh.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -1057,6 +1057,19 @@ const zh = {
tasksOnly: '仅任务',
leaveCommentPlaceholder: '留下评论… (Ctrl+Enter 提交)',
noActivity: '暂无活动记录',
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: '全部',
createsFilter: '创建',
deletesFilter: '删除',
statusChangesFilter: '状态变更',
activityEmptyValue: '(空)',
activityFieldChanged: '将 {{field}} 从“{{old}}”改为“{{new}}”',
activityCreated: '创建了此记录',
activityDeleted: '删除了此记录',
activityStatusChanged: '将状态改为“{{value}}”',
activityUpdated: '更新了记录',
loadMore: '加载更多',
edited: '(已编辑)',
via: '通过 {{source}}',
Expand Down
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .changeset/7149-activity-timeline-remaining-literals.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
---
'@object-ui/plugin-detail': patch
'@object-ui/i18n': patch
---

`ActivityTimeline` speaks the session locale — the other 18 literals
(objectui#7149).

objectui#7142 gave this component its first `t()` call (the empty-state title)
and filed the sweep that found the rest. Until now a zh activity tab read
`"Activity(0)暂无活动记录"`: one translated string in a component that was
otherwise entirely English.

All 18 now resolve from the ten packs, in three groups:

- **Relative timestamps and the card title** (`just now`, `{{count}}m/h/d ago`,
`Activity`) — these render on *every* activity tab. All five were a pure
lookup swap: the `en` pack value was already byte-identical to the literal,
and the sibling `RecordActivityTimeline` already used the same keys.
- **The `formatFieldChange` sentences** — assembled in code, so they needed new
keys *with* interpolation holes rather than a lookup. Same reachability as the
timestamps: they render for any entry whose optional `description` is absent.
The quotes live inside each pack's value, so every locale punctuates its own
way (de `„…“`, zh `“…”`, ja `「…」`, fr/ru `«…»`).
- **The six filter chips and the chip group's accessible name** — reachable only
through the published export, since no host in this repo passes `filterable`.

Ten new `detail.*` keys across all ten packs (no inline `defaultValue` —
objectui#3517), mirrored byte-for-byte into `DETAIL_DEFAULT_TRANSLATIONS` so a
provider-less host still reads English rather than a raw key.

One deliberate English copy change: the chip group's `aria-label` was
`"Activity type filter"` and now resolves `detail.filterActivity`
(`"Filter activity"`) — the key `RecordActivityTimeline` already uses for the
accessible name of its own activity filter, so one control does not carry two
names across two components.

Also drops the unused `Filter` import (a pre-existing eslint warning).
20 changes: 13 additions & 7 deletions packages/i18n/src/__tests__/de-quote-pairing-3876.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -268,8 +268,13 @@ describe('objectui#3876 — de pack closes „ with “ and not with a straight
// 55 once objectui#6655 added `timeline.unsupported.objectBoundGantt`, the
// object-bound timeline's refusal of `variant: gantt`, which names the
// refused variant — „gantt“, a literal span, because the quoted thing is an
// authoring value the author typed rather than data the runtime filled in.
expect(okSpans, 'correctly paired spans').toBe(55);
// authoring value the author typed rather than data the runtime filled in,
// 58 once objectui#7149 gave `ActivityTimeline`'s assembled sentences pack
// keys: `detail.activityFieldChanged` quotes the OLD and NEW field values
// („{{old}}“ / „{{new}}“, two spans in one value, like `navigationSync.
// renamedPage` above) and `detail.activityStatusChanged` the new status
// („{{value}}“) — three interpolated spans, all runtime data.
expect(okSpans, 'correctly paired spans').toBe(58);
});

it('keeps the count identity that replaces the card’s count(„) === count(“)', () => {
Expand All@@ -289,11 +294,12 @@ describe('objectui#3876 — de pack closes „ with “ and not with a straight
// 53 / 53 / 0 after objectui#5232 added
// `console.objectView.viewConfigPermissionDenied`; 54 / 54 / 0 after
// objectui#6301 added `packagedAutomation.cloneCreated`; 55 / 55 / 0 after
// objectui#6655 added `timeline.unsupported.objectBoundGantt`. `rdq` staying
// at 0 is the load-bearing half: each new value added a MATCHED „…“ pair,
// not a stray closer that would have made `close === open` true for the
// wrong reason.
expect({ open, close, rdq }).toEqual({ open: 55, close: 55, rdq: 0 });
// objectui#6655 added `timeline.unsupported.objectBoundGantt`; 58 / 58 / 0
// after objectui#7149 added the two quoted `ActivityTimeline` sentences
// (three spans between them). `rdq` staying at 0 is the load-bearing half:
// each new value added a MATCHED „…“ pair, not a stray closer that would
// have made `close === open` true for the wrong reason.
expect({ open, close, rdq }).toEqual({ open: 58, close: 58, rdq: 0 });
// The durable shape: every „ closed by a “, every surplus “ an English
// opener answered by a ”. Survived translating the two English values.
expect(close).toBe(open + rdq);
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/ar.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -960,6 +960,19 @@ const ar = {
tasksOnly: "المهام فقط",
leaveCommentPlaceholder: "اترك تعليقاً… (Ctrl+Enter للإرسال)",
noActivity: "لا يوجد نشاط مسجل",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'الكل',
createsFilter: 'عمليات الإنشاء',
deletesFilter: 'عمليات الحذف',
statusChangesFilter: 'تغييرات الحالة',
activityEmptyValue: '(فارغ)',
activityFieldChanged: 'غيّر {{field}} من "{{old}}" إلى "{{new}}"',
activityCreated: 'أنشأ هذا السجل',
activityDeleted: 'حذف هذا السجل',
activityStatusChanged: 'غيّر الحالة إلى "{{value}}"',
activityUpdated: 'حدّث السجل',
loadMore: "تحميل المزيد",
edited: "(معدل)",
via: "عبر {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/de.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -954,6 +954,19 @@ const de = {
tasksOnly: "Nur Aufgaben",
leaveCommentPlaceholder: "Kommentar hinterlassen… (Strg+Enter zum Senden)",
noActivity: "Keine Aktivitäten aufgezeichnet",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'Alle',
createsFilter: 'Erstellungen',
deletesFilter: 'Löschungen',
statusChangesFilter: 'Statusänderungen',
activityEmptyValue: '(leer)',
activityFieldChanged: '{{field}} von „{{old}}“ zu „{{new}}“ geändert',
activityCreated: 'Diesen Datensatz erstellt',
activityDeleted: 'Diesen Datensatz gelöscht',
activityStatusChanged: 'Status zu „{{value}}“ geändert',
activityUpdated: 'Datensatz aktualisiert',
loadMore: "Mehr laden",
edited: "(bearbeitet)",
via: "über {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/en.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -1168,6 +1168,19 @@ const en = {
tasksOnly: 'Tasks Only',
leaveCommentPlaceholder: 'Leave a comment… (Ctrl+Enter to submit)',
noActivity: 'No activity recorded',
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'All',
createsFilter: 'Creates',
deletesFilter: 'Deletes',
statusChangesFilter: 'Status Changes',
activityEmptyValue: '(empty)',
activityFieldChanged: 'Changed {{field}} from "{{old}}" to "{{new}}"',
activityCreated: 'Created this record',
activityDeleted: 'Deleted this record',
activityStatusChanged: 'Changed status to "{{value}}"',
activityUpdated: 'Updated record',
loadMore: 'Load more',
edited: '(edited)',
via: 'via {{source}}',
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/es.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -958,6 +958,19 @@ const es = {
tasksOnly: "Solo tareas",
leaveCommentPlaceholder: "Deja un comentario… (Ctrl+Enter para enviar)",
noActivity: "Sin actividad registrada",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'Todo',
createsFilter: 'Creaciones',
deletesFilter: 'Eliminaciones',
statusChangesFilter: 'Cambios de estado',
activityEmptyValue: '(vacío)',
activityFieldChanged: 'Cambió {{field}} de "{{old}}" a "{{new}}"',
activityCreated: 'Creó este registro',
activityDeleted: 'Eliminó este registro',
activityStatusChanged: 'Cambió el estado a "{{value}}"',
activityUpdated: 'Actualizó el registro',
loadMore: "Cargar más",
edited: "(editado)",
via: "vía {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/fr.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -956,6 +956,19 @@ const fr = {
tasksOnly: "Tâches uniquement",
leaveCommentPlaceholder: "Laisser un commentaire… (Ctrl+Entrée pour envoyer)",
noActivity: "Aucune activité enregistrée",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'Tout',
createsFilter: 'Créations',
deletesFilter: 'Suppressions',
statusChangesFilter: 'Changements de statut',
activityEmptyValue: '(vide)',
activityFieldChanged: '{{field}} modifié de « {{old}} » à « {{new}} »',
activityCreated: 'A créé cet enregistrement',
activityDeleted: 'A supprimé cet enregistrement',
activityStatusChanged: 'A changé le statut en « {{value}} »',
activityUpdated: 'A mis à jour l\'enregistrement',
loadMore: "Charger plus",
edited: "(modifié)",
via: "via {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/ja.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -965,6 +965,19 @@ const ja = {
tasksOnly: "タスクのみ",
leaveCommentPlaceholder: "コメントを入力… (Ctrl+Enterで送信)",
noActivity: "アクティビティの記録なし",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'すべて',
createsFilter: '作成',
deletesFilter: '削除',
statusChangesFilter: 'ステータス変更',
activityEmptyValue: '(空)',
activityFieldChanged: '{{field}} を「{{old}}」から「{{new}}」に変更しました',
activityCreated: 'このレコードを作成しました',
activityDeleted: 'このレコードを削除しました',
activityStatusChanged: 'ステータスを「{{value}}」に変更しました',
activityUpdated: 'レコードを更新しました',
loadMore: "さらに読み込む",
edited: "(編集済み)",
via: "{{source}} 経由",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/ko.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -954,6 +954,19 @@ const ko = {
tasksOnly: "작업만",
leaveCommentPlaceholder: "댓글 남기기… (Ctrl+Enter로 제출)",
noActivity: "기록된 활동 없음",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: '전체',
createsFilter: '생성',
deletesFilter: '삭제',
statusChangesFilter: '상태 변경',
activityEmptyValue: '(비어 있음)',
activityFieldChanged: '{{field}}을(를) "{{old}}"에서 "{{new}}"(으)로 변경했습니다',
activityCreated: '이 레코드를 만들었습니다',
activityDeleted: '이 레코드를 삭제했습니다',
activityStatusChanged: '상태를 "{{value}}"(으)로 변경했습니다',
activityUpdated: '레코드를 업데이트했습니다',
loadMore: "더 보기",
edited: "(수정됨)",
via: "{{source}} 통해",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/pt.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -955,6 +955,19 @@ const pt = {
tasksOnly: "Apenas tarefas",
leaveCommentPlaceholder: "Deixar um comentário… (Ctrl+Enter para enviar)",
noActivity: "Nenhuma atividade registrada",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'Tudo',
createsFilter: 'Criações',
deletesFilter: 'Exclusões',
statusChangesFilter: 'Alterações de status',
activityEmptyValue: '(vazio)',
activityFieldChanged: 'Alterou {{field}} de "{{old}}" para "{{new}}"',
activityCreated: 'Criou este registro',
activityDeleted: 'Excluiu este registro',
activityStatusChanged: 'Alterou o status para "{{value}}"',
activityUpdated: 'Atualizou o registro',
loadMore: "Carregar mais",
edited: "(editado)",
via: "via {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/ru.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -973,6 +973,19 @@ const ru = {
tasksOnly: "Только задачи",
leaveCommentPlaceholder: "Оставить комментарий… (Ctrl+Enter для отправки)",
noActivity: "Нет зарегистрированной активности",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'Все',
createsFilter: 'Создания',
deletesFilter: 'Удаления',
statusChangesFilter: 'Изменения статуса',
activityEmptyValue: '(пусто)',
activityFieldChanged: 'Изменено поле {{field}} с «{{old}}» на «{{new}}»',
activityCreated: 'Создал эту запись',
activityDeleted: 'Удалил эту запись',
activityStatusChanged: 'Изменил статус на «{{value}}»',
activityUpdated: 'Обновил запись',
loadMore: "Загрузить ещё",
edited: "(изменено)",
via: "через {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/zh.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -1057,6 +1057,19 @@ const zh = {
tasksOnly: '仅任务',
leaveCommentPlaceholder: '留下评论… (Ctrl+Enter 提交)',
noActivity: '暂无活动记录',
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: '全部',
createsFilter: '创建',
deletesFilter: '删除',
statusChangesFilter: '状态变更',
activityEmptyValue: '(空)',
activityFieldChanged: '将 {{field}} 从“{{old}}”改为“{{new}}”',
activityCreated: '创建了此记录',
activityDeleted: '删除了此记录',
activityStatusChanged: '将状态改为“{{value}}”',
activityUpdated: '更新了记录',
loadMore: '加载更多',
edited: '(已编辑)',
via: '通过 {{source}}',
Expand Down
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .changeset/7149-activity-timeline-remaining-literals.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
---
'@object-ui/plugin-detail': patch
'@object-ui/i18n': patch
---

`ActivityTimeline` speaks the session locale — the other 18 literals
(objectui#7149).

objectui#7142 gave this component its first `t()` call (the empty-state title)
and filed the sweep that found the rest. Until now a zh activity tab read
`"Activity(0)暂无活动记录"`: one translated string in a component that was
otherwise entirely English.

All 18 now resolve from the ten packs, in three groups:

- **Relative timestamps and the card title** (`just now`, `{{count}}m/h/d ago`,
`Activity`) — these render on *every* activity tab. All five were a pure
lookup swap: the `en` pack value was already byte-identical to the literal,
and the sibling `RecordActivityTimeline` already used the same keys.
- **The `formatFieldChange` sentences** — assembled in code, so they needed new
keys *with* interpolation holes rather than a lookup. Same reachability as the
timestamps: they render for any entry whose optional `description` is absent.
The quotes live inside each pack's value, so every locale punctuates its own
way (de `„…“`, zh `“…”`, ja `「…」`, fr/ru `«…»`).
- **The six filter chips and the chip group's accessible name** — reachable only
through the published export, since no host in this repo passes `filterable`.

Ten new `detail.*` keys across all ten packs (no inline `defaultValue` —
objectui#3517), mirrored byte-for-byte into `DETAIL_DEFAULT_TRANSLATIONS` so a
provider-less host still reads English rather than a raw key.

One deliberate English copy change: the chip group's `aria-label` was
`"Activity type filter"` and now resolves `detail.filterActivity`
(`"Filter activity"`) — the key `RecordActivityTimeline` already uses for the
accessible name of its own activity filter, so one control does not carry two
names across two components.

Also drops the unused `Filter` import (a pre-existing eslint warning).
20 changes: 13 additions & 7 deletions packages/i18n/src/__tests__/de-quote-pairing-3876.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -268,8 +268,13 @@ describe('objectui#3876 — de pack closes „ with “ and not with a straight
// 55 once objectui#6655 added `timeline.unsupported.objectBoundGantt`, the
// object-bound timeline's refusal of `variant: gantt`, which names the
// refused variant — „gantt“, a literal span, because the quoted thing is an
// authoring value the author typed rather than data the runtime filled in.
expect(okSpans, 'correctly paired spans').toBe(55);
// authoring value the author typed rather than data the runtime filled in,
// 58 once objectui#7149 gave `ActivityTimeline`'s assembled sentences pack
// keys: `detail.activityFieldChanged` quotes the OLD and NEW field values
// („{{old}}“ / „{{new}}“, two spans in one value, like `navigationSync.
// renamedPage` above) and `detail.activityStatusChanged` the new status
// („{{value}}“) — three interpolated spans, all runtime data.
expect(okSpans, 'correctly paired spans').toBe(58);
});

it('keeps the count identity that replaces the card’s count(„) === count(“)', () => {
Expand All@@ -289,11 +294,12 @@ describe('objectui#3876 — de pack closes „ with “ and not with a straight
// 53 / 53 / 0 after objectui#5232 added
// `console.objectView.viewConfigPermissionDenied`; 54 / 54 / 0 after
// objectui#6301 added `packagedAutomation.cloneCreated`; 55 / 55 / 0 after
// objectui#6655 added `timeline.unsupported.objectBoundGantt`. `rdq` staying
// at 0 is the load-bearing half: each new value added a MATCHED „…“ pair,
// not a stray closer that would have made `close === open` true for the
// wrong reason.
expect({ open, close, rdq }).toEqual({ open: 55, close: 55, rdq: 0 });
// objectui#6655 added `timeline.unsupported.objectBoundGantt`; 58 / 58 / 0
// after objectui#7149 added the two quoted `ActivityTimeline` sentences
// (three spans between them). `rdq` staying at 0 is the load-bearing half:
// each new value added a MATCHED „…“ pair, not a stray closer that would
// have made `close === open` true for the wrong reason.
expect({ open, close, rdq }).toEqual({ open: 58, close: 58, rdq: 0 });
// The durable shape: every „ closed by a “, every surplus “ an English
// opener answered by a ”. Survived translating the two English values.
expect(close).toBe(open + rdq);
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/ar.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -960,6 +960,19 @@ const ar = {
tasksOnly: "المهام فقط",
leaveCommentPlaceholder: "اترك تعليقاً… (Ctrl+Enter للإرسال)",
noActivity: "لا يوجد نشاط مسجل",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'الكل',
createsFilter: 'عمليات الإنشاء',
deletesFilter: 'عمليات الحذف',
statusChangesFilter: 'تغييرات الحالة',
activityEmptyValue: '(فارغ)',
activityFieldChanged: 'غيّر {{field}} من "{{old}}" إلى "{{new}}"',
activityCreated: 'أنشأ هذا السجل',
activityDeleted: 'حذف هذا السجل',
activityStatusChanged: 'غيّر الحالة إلى "{{value}}"',
activityUpdated: 'حدّث السجل',
loadMore: "تحميل المزيد",
edited: "(معدل)",
via: "عبر {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/de.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -954,6 +954,19 @@ const de = {
tasksOnly: "Nur Aufgaben",
leaveCommentPlaceholder: "Kommentar hinterlassen… (Strg+Enter zum Senden)",
noActivity: "Keine Aktivitäten aufgezeichnet",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'Alle',
createsFilter: 'Erstellungen',
deletesFilter: 'Löschungen',
statusChangesFilter: 'Statusänderungen',
activityEmptyValue: '(leer)',
activityFieldChanged: '{{field}} von „{{old}}“ zu „{{new}}“ geändert',
activityCreated: 'Diesen Datensatz erstellt',
activityDeleted: 'Diesen Datensatz gelöscht',
activityStatusChanged: 'Status zu „{{value}}“ geändert',
activityUpdated: 'Datensatz aktualisiert',
loadMore: "Mehr laden",
edited: "(bearbeitet)",
via: "über {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/en.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -1168,6 +1168,19 @@ const en = {
tasksOnly: 'Tasks Only',
leaveCommentPlaceholder: 'Leave a comment… (Ctrl+Enter to submit)',
noActivity: 'No activity recorded',
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'All',
createsFilter: 'Creates',
deletesFilter: 'Deletes',
statusChangesFilter: 'Status Changes',
activityEmptyValue: '(empty)',
activityFieldChanged: 'Changed {{field}} from "{{old}}" to "{{new}}"',
activityCreated: 'Created this record',
activityDeleted: 'Deleted this record',
activityStatusChanged: 'Changed status to "{{value}}"',
activityUpdated: 'Updated record',
loadMore: 'Load more',
edited: '(edited)',
via: 'via {{source}}',
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/es.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -958,6 +958,19 @@ const es = {
tasksOnly: "Solo tareas",
leaveCommentPlaceholder: "Deja un comentario… (Ctrl+Enter para enviar)",
noActivity: "Sin actividad registrada",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'Todo',
createsFilter: 'Creaciones',
deletesFilter: 'Eliminaciones',
statusChangesFilter: 'Cambios de estado',
activityEmptyValue: '(vacío)',
activityFieldChanged: 'Cambió {{field}} de "{{old}}" a "{{new}}"',
activityCreated: 'Creó este registro',
activityDeleted: 'Eliminó este registro',
activityStatusChanged: 'Cambió el estado a "{{value}}"',
activityUpdated: 'Actualizó el registro',
loadMore: "Cargar más",
edited: "(editado)",
via: "vía {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/fr.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -956,6 +956,19 @@ const fr = {
tasksOnly: "Tâches uniquement",
leaveCommentPlaceholder: "Laisser un commentaire… (Ctrl+Entrée pour envoyer)",
noActivity: "Aucune activité enregistrée",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'Tout',
createsFilter: 'Créations',
deletesFilter: 'Suppressions',
statusChangesFilter: 'Changements de statut',
activityEmptyValue: '(vide)',
activityFieldChanged: '{{field}} modifié de « {{old}} » à « {{new}} »',
activityCreated: 'A créé cet enregistrement',
activityDeleted: 'A supprimé cet enregistrement',
activityStatusChanged: 'A changé le statut en « {{value}} »',
activityUpdated: 'A mis à jour l\'enregistrement',
loadMore: "Charger plus",
edited: "(modifié)",
via: "via {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/ja.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -965,6 +965,19 @@ const ja = {
tasksOnly: "タスクのみ",
leaveCommentPlaceholder: "コメントを入力… (Ctrl+Enterで送信)",
noActivity: "アクティビティの記録なし",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'すべて',
createsFilter: '作成',
deletesFilter: '削除',
statusChangesFilter: 'ステータス変更',
activityEmptyValue: '(空)',
activityFieldChanged: '{{field}} を「{{old}}」から「{{new}}」に変更しました',
activityCreated: 'このレコードを作成しました',
activityDeleted: 'このレコードを削除しました',
activityStatusChanged: 'ステータスを「{{value}}」に変更しました',
activityUpdated: 'レコードを更新しました',
loadMore: "さらに読み込む",
edited: "(編集済み)",
via: "{{source}} 経由",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/ko.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -954,6 +954,19 @@ const ko = {
tasksOnly: "작업만",
leaveCommentPlaceholder: "댓글 남기기… (Ctrl+Enter로 제출)",
noActivity: "기록된 활동 없음",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: '전체',
createsFilter: '생성',
deletesFilter: '삭제',
statusChangesFilter: '상태 변경',
activityEmptyValue: '(비어 있음)',
activityFieldChanged: '{{field}}을(를) "{{old}}"에서 "{{new}}"(으)로 변경했습니다',
activityCreated: '이 레코드를 만들었습니다',
activityDeleted: '이 레코드를 삭제했습니다',
activityStatusChanged: '상태를 "{{value}}"(으)로 변경했습니다',
activityUpdated: '레코드를 업데이트했습니다',
loadMore: "더 보기",
edited: "(수정됨)",
via: "{{source}} 통해",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/pt.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -955,6 +955,19 @@ const pt = {
tasksOnly: "Apenas tarefas",
leaveCommentPlaceholder: "Deixar um comentário… (Ctrl+Enter para enviar)",
noActivity: "Nenhuma atividade registrada",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'Tudo',
createsFilter: 'Criações',
deletesFilter: 'Exclusões',
statusChangesFilter: 'Alterações de status',
activityEmptyValue: '(vazio)',
activityFieldChanged: 'Alterou {{field}} de "{{old}}" para "{{new}}"',
activityCreated: 'Criou este registro',
activityDeleted: 'Excluiu este registro',
activityStatusChanged: 'Alterou o status para "{{value}}"',
activityUpdated: 'Atualizou o registro',
loadMore: "Carregar mais",
edited: "(editado)",
via: "via {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/ru.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -973,6 +973,19 @@ const ru = {
tasksOnly: "Только задачи",
leaveCommentPlaceholder: "Оставить комментарий… (Ctrl+Enter для отправки)",
noActivity: "Нет зарегистрированной активности",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'Все',
createsFilter: 'Создания',
deletesFilter: 'Удаления',
statusChangesFilter: 'Изменения статуса',
activityEmptyValue: '(пусто)',
activityFieldChanged: 'Изменено поле {{field}} с «{{old}}» на «{{new}}»',
activityCreated: 'Создал эту запись',
activityDeleted: 'Удалил эту запись',
activityStatusChanged: 'Изменил статус на «{{value}}»',
activityUpdated: 'Обновил запись',
loadMore: "Загрузить ещё",
edited: "(изменено)",
via: "через {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/zh.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -1057,6 +1057,19 @@ const zh = {
tasksOnly: '仅任务',
leaveCommentPlaceholder: '留下评论… (Ctrl+Enter 提交)',
noActivity: '暂无活动记录',
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: '全部',
createsFilter: '创建',
deletesFilter: '删除',
statusChangesFilter: '状态变更',
activityEmptyValue: '(空)',
activityFieldChanged: '将 {{field}} 从“{{old}}”改为“{{new}}”',
activityCreated: '创建了此记录',
activityDeleted: '删除了此记录',
activityStatusChanged: '将状态改为“{{value}}”',
activityUpdated: '更新了记录',
loadMore: '加载更多',
edited: '(已编辑)',
via: '通过 {{source}}',
Expand Down
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .changeset/7149-activity-timeline-remaining-literals.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
---
'@object-ui/plugin-detail': patch
'@object-ui/i18n': patch
---

`ActivityTimeline` speaks the session locale — the other 18 literals
(objectui#7149).

objectui#7142 gave this component its first `t()` call (the empty-state title)
and filed the sweep that found the rest. Until now a zh activity tab read
`"Activity(0)暂无活动记录"`: one translated string in a component that was
otherwise entirely English.

All 18 now resolve from the ten packs, in three groups:

- **Relative timestamps and the card title** (`just now`, `{{count}}m/h/d ago`,
`Activity`) — these render on *every* activity tab. All five were a pure
lookup swap: the `en` pack value was already byte-identical to the literal,
and the sibling `RecordActivityTimeline` already used the same keys.
- **The `formatFieldChange` sentences** — assembled in code, so they needed new
keys *with* interpolation holes rather than a lookup. Same reachability as the
timestamps: they render for any entry whose optional `description` is absent.
The quotes live inside each pack's value, so every locale punctuates its own
way (de `„…“`, zh `“…”`, ja `「…」`, fr/ru `«…»`).
- **The six filter chips and the chip group's accessible name** — reachable only
through the published export, since no host in this repo passes `filterable`.

Ten new `detail.*` keys across all ten packs (no inline `defaultValue` —
objectui#3517), mirrored byte-for-byte into `DETAIL_DEFAULT_TRANSLATIONS` so a
provider-less host still reads English rather than a raw key.

One deliberate English copy change: the chip group's `aria-label` was
`"Activity type filter"` and now resolves `detail.filterActivity`
(`"Filter activity"`) — the key `RecordActivityTimeline` already uses for the
accessible name of its own activity filter, so one control does not carry two
names across two components.

Also drops the unused `Filter` import (a pre-existing eslint warning).
20 changes: 13 additions & 7 deletions packages/i18n/src/__tests__/de-quote-pairing-3876.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -268,8 +268,13 @@ describe('objectui#3876 — de pack closes „ with “ and not with a straight
// 55 once objectui#6655 added `timeline.unsupported.objectBoundGantt`, the
// object-bound timeline's refusal of `variant: gantt`, which names the
// refused variant — „gantt“, a literal span, because the quoted thing is an
// authoring value the author typed rather than data the runtime filled in.
expect(okSpans, 'correctly paired spans').toBe(55);
// authoring value the author typed rather than data the runtime filled in,
// 58 once objectui#7149 gave `ActivityTimeline`'s assembled sentences pack
// keys: `detail.activityFieldChanged` quotes the OLD and NEW field values
// („{{old}}“ / „{{new}}“, two spans in one value, like `navigationSync.
// renamedPage` above) and `detail.activityStatusChanged` the new status
// („{{value}}“) — three interpolated spans, all runtime data.
expect(okSpans, 'correctly paired spans').toBe(58);
});

it('keeps the count identity that replaces the card’s count(„) === count(“)', () => {
Expand All@@ -289,11 +294,12 @@ describe('objectui#3876 — de pack closes „ with “ and not with a straight
// 53 / 53 / 0 after objectui#5232 added
// `console.objectView.viewConfigPermissionDenied`; 54 / 54 / 0 after
// objectui#6301 added `packagedAutomation.cloneCreated`; 55 / 55 / 0 after
// objectui#6655 added `timeline.unsupported.objectBoundGantt`. `rdq` staying
// at 0 is the load-bearing half: each new value added a MATCHED „…“ pair,
// not a stray closer that would have made `close === open` true for the
// wrong reason.
expect({ open, close, rdq }).toEqual({ open: 55, close: 55, rdq: 0 });
// objectui#6655 added `timeline.unsupported.objectBoundGantt`; 58 / 58 / 0
// after objectui#7149 added the two quoted `ActivityTimeline` sentences
// (three spans between them). `rdq` staying at 0 is the load-bearing half:
// each new value added a MATCHED „…“ pair, not a stray closer that would
// have made `close === open` true for the wrong reason.
expect({ open, close, rdq }).toEqual({ open: 58, close: 58, rdq: 0 });
// The durable shape: every „ closed by a “, every surplus “ an English
// opener answered by a ”. Survived translating the two English values.
expect(close).toBe(open + rdq);
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/ar.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -960,6 +960,19 @@ const ar = {
tasksOnly: "المهام فقط",
leaveCommentPlaceholder: "اترك تعليقاً… (Ctrl+Enter للإرسال)",
noActivity: "لا يوجد نشاط مسجل",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'الكل',
createsFilter: 'عمليات الإنشاء',
deletesFilter: 'عمليات الحذف',
statusChangesFilter: 'تغييرات الحالة',
activityEmptyValue: '(فارغ)',
activityFieldChanged: 'غيّر {{field}} من "{{old}}" إلى "{{new}}"',
activityCreated: 'أنشأ هذا السجل',
activityDeleted: 'حذف هذا السجل',
activityStatusChanged: 'غيّر الحالة إلى "{{value}}"',
activityUpdated: 'حدّث السجل',
loadMore: "تحميل المزيد",
edited: "(معدل)",
via: "عبر {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/de.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -954,6 +954,19 @@ const de = {
tasksOnly: "Nur Aufgaben",
leaveCommentPlaceholder: "Kommentar hinterlassen… (Strg+Enter zum Senden)",
noActivity: "Keine Aktivitäten aufgezeichnet",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'Alle',
createsFilter: 'Erstellungen',
deletesFilter: 'Löschungen',
statusChangesFilter: 'Statusänderungen',
activityEmptyValue: '(leer)',
activityFieldChanged: '{{field}} von „{{old}}“ zu „{{new}}“ geändert',
activityCreated: 'Diesen Datensatz erstellt',
activityDeleted: 'Diesen Datensatz gelöscht',
activityStatusChanged: 'Status zu „{{value}}“ geändert',
activityUpdated: 'Datensatz aktualisiert',
loadMore: "Mehr laden",
edited: "(bearbeitet)",
via: "über {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/en.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -1168,6 +1168,19 @@ const en = {
tasksOnly: 'Tasks Only',
leaveCommentPlaceholder: 'Leave a comment… (Ctrl+Enter to submit)',
noActivity: 'No activity recorded',
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'All',
createsFilter: 'Creates',
deletesFilter: 'Deletes',
statusChangesFilter: 'Status Changes',
activityEmptyValue: '(empty)',
activityFieldChanged: 'Changed {{field}} from "{{old}}" to "{{new}}"',
activityCreated: 'Created this record',
activityDeleted: 'Deleted this record',
activityStatusChanged: 'Changed status to "{{value}}"',
activityUpdated: 'Updated record',
loadMore: 'Load more',
edited: '(edited)',
via: 'via {{source}}',
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/es.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -958,6 +958,19 @@ const es = {
tasksOnly: "Solo tareas",
leaveCommentPlaceholder: "Deja un comentario… (Ctrl+Enter para enviar)",
noActivity: "Sin actividad registrada",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'Todo',
createsFilter: 'Creaciones',
deletesFilter: 'Eliminaciones',
statusChangesFilter: 'Cambios de estado',
activityEmptyValue: '(vacío)',
activityFieldChanged: 'Cambió {{field}} de "{{old}}" a "{{new}}"',
activityCreated: 'Creó este registro',
activityDeleted: 'Eliminó este registro',
activityStatusChanged: 'Cambió el estado a "{{value}}"',
activityUpdated: 'Actualizó el registro',
loadMore: "Cargar más",
edited: "(editado)",
via: "vía {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/fr.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -956,6 +956,19 @@ const fr = {
tasksOnly: "Tâches uniquement",
leaveCommentPlaceholder: "Laisser un commentaire… (Ctrl+Entrée pour envoyer)",
noActivity: "Aucune activité enregistrée",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'Tout',
createsFilter: 'Créations',
deletesFilter: 'Suppressions',
statusChangesFilter: 'Changements de statut',
activityEmptyValue: '(vide)',
activityFieldChanged: '{{field}} modifié de « {{old}} » à « {{new}} »',
activityCreated: 'A créé cet enregistrement',
activityDeleted: 'A supprimé cet enregistrement',
activityStatusChanged: 'A changé le statut en « {{value}} »',
activityUpdated: 'A mis à jour l\'enregistrement',
loadMore: "Charger plus",
edited: "(modifié)",
via: "via {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/ja.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -965,6 +965,19 @@ const ja = {
tasksOnly: "タスクのみ",
leaveCommentPlaceholder: "コメントを入力… (Ctrl+Enterで送信)",
noActivity: "アクティビティの記録なし",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'すべて',
createsFilter: '作成',
deletesFilter: '削除',
statusChangesFilter: 'ステータス変更',
activityEmptyValue: '(空)',
activityFieldChanged: '{{field}} を「{{old}}」から「{{new}}」に変更しました',
activityCreated: 'このレコードを作成しました',
activityDeleted: 'このレコードを削除しました',
activityStatusChanged: 'ステータスを「{{value}}」に変更しました',
activityUpdated: 'レコードを更新しました',
loadMore: "さらに読み込む",
edited: "(編集済み)",
via: "{{source}} 経由",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/ko.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -954,6 +954,19 @@ const ko = {
tasksOnly: "작업만",
leaveCommentPlaceholder: "댓글 남기기… (Ctrl+Enter로 제출)",
noActivity: "기록된 활동 없음",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: '전체',
createsFilter: '생성',
deletesFilter: '삭제',
statusChangesFilter: '상태 변경',
activityEmptyValue: '(비어 있음)',
activityFieldChanged: '{{field}}을(를) "{{old}}"에서 "{{new}}"(으)로 변경했습니다',
activityCreated: '이 레코드를 만들었습니다',
activityDeleted: '이 레코드를 삭제했습니다',
activityStatusChanged: '상태를 "{{value}}"(으)로 변경했습니다',
activityUpdated: '레코드를 업데이트했습니다',
loadMore: "더 보기",
edited: "(수정됨)",
via: "{{source}} 통해",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/pt.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -955,6 +955,19 @@ const pt = {
tasksOnly: "Apenas tarefas",
leaveCommentPlaceholder: "Deixar um comentário… (Ctrl+Enter para enviar)",
noActivity: "Nenhuma atividade registrada",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'Tudo',
createsFilter: 'Criações',
deletesFilter: 'Exclusões',
statusChangesFilter: 'Alterações de status',
activityEmptyValue: '(vazio)',
activityFieldChanged: 'Alterou {{field}} de "{{old}}" para "{{new}}"',
activityCreated: 'Criou este registro',
activityDeleted: 'Excluiu este registro',
activityStatusChanged: 'Alterou o status para "{{value}}"',
activityUpdated: 'Atualizou o registro',
loadMore: "Carregar mais",
edited: "(editado)",
via: "via {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/ru.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -973,6 +973,19 @@ const ru = {
tasksOnly: "Только задачи",
leaveCommentPlaceholder: "Оставить комментарий… (Ctrl+Enter для отправки)",
noActivity: "Нет зарегистрированной активности",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'Все',
createsFilter: 'Создания',
deletesFilter: 'Удаления',
statusChangesFilter: 'Изменения статуса',
activityEmptyValue: '(пусто)',
activityFieldChanged: 'Изменено поле {{field}} с «{{old}}» на «{{new}}»',
activityCreated: 'Создал эту запись',
activityDeleted: 'Удалил эту запись',
activityStatusChanged: 'Изменил статус на «{{value}}»',
activityUpdated: 'Обновил запись',
loadMore: "Загрузить ещё",
edited: "(изменено)",
via: "через {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/zh.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -1057,6 +1057,19 @@ const zh = {
tasksOnly: '仅任务',
leaveCommentPlaceholder: '留下评论… (Ctrl+Enter 提交)',
noActivity: '暂无活动记录',
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: '全部',
createsFilter: '创建',
deletesFilter: '删除',
statusChangesFilter: '状态变更',
activityEmptyValue: '(空)',
activityFieldChanged: '将 {{field}} 从“{{old}}”改为“{{new}}”',
activityCreated: '创建了此记录',
activityDeleted: '删除了此记录',
activityStatusChanged: '将状态改为“{{value}}”',
activityUpdated: '更新了记录',
loadMore: '加载更多',
edited: '(已编辑)',
via: '通过 {{source}}',
Expand Down
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .changeset/7149-activity-timeline-remaining-literals.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
---
'@object-ui/plugin-detail': patch
'@object-ui/i18n': patch
---

`ActivityTimeline` speaks the session locale — the other 18 literals
(objectui#7149).

objectui#7142 gave this component its first `t()` call (the empty-state title)
and filed the sweep that found the rest. Until now a zh activity tab read
`"Activity(0)暂无活动记录"`: one translated string in a component that was
otherwise entirely English.

All 18 now resolve from the ten packs, in three groups:

- **Relative timestamps and the card title** (`just now`, `{{count}}m/h/d ago`,
`Activity`) — these render on *every* activity tab. All five were a pure
lookup swap: the `en` pack value was already byte-identical to the literal,
and the sibling `RecordActivityTimeline` already used the same keys.
- **The `formatFieldChange` sentences** — assembled in code, so they needed new
keys *with* interpolation holes rather than a lookup. Same reachability as the
timestamps: they render for any entry whose optional `description` is absent.
The quotes live inside each pack's value, so every locale punctuates its own
way (de `„…“`, zh `“…”`, ja `「…」`, fr/ru `«…»`).
- **The six filter chips and the chip group's accessible name** — reachable only
through the published export, since no host in this repo passes `filterable`.

Ten new `detail.*` keys across all ten packs (no inline `defaultValue` —
objectui#3517), mirrored byte-for-byte into `DETAIL_DEFAULT_TRANSLATIONS` so a
provider-less host still reads English rather than a raw key.

One deliberate English copy change: the chip group's `aria-label` was
`"Activity type filter"` and now resolves `detail.filterActivity`
(`"Filter activity"`) — the key `RecordActivityTimeline` already uses for the
accessible name of its own activity filter, so one control does not carry two
names across two components.

Also drops the unused `Filter` import (a pre-existing eslint warning).
20 changes: 13 additions & 7 deletions packages/i18n/src/__tests__/de-quote-pairing-3876.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -268,8 +268,13 @@ describe('objectui#3876 — de pack closes „ with “ and not with a straight
// 55 once objectui#6655 added `timeline.unsupported.objectBoundGantt`, the
// object-bound timeline's refusal of `variant: gantt`, which names the
// refused variant — „gantt“, a literal span, because the quoted thing is an
// authoring value the author typed rather than data the runtime filled in.
expect(okSpans, 'correctly paired spans').toBe(55);
// authoring value the author typed rather than data the runtime filled in,
// 58 once objectui#7149 gave `ActivityTimeline`'s assembled sentences pack
// keys: `detail.activityFieldChanged` quotes the OLD and NEW field values
// („{{old}}“ / „{{new}}“, two spans in one value, like `navigationSync.
// renamedPage` above) and `detail.activityStatusChanged` the new status
// („{{value}}“) — three interpolated spans, all runtime data.
expect(okSpans, 'correctly paired spans').toBe(58);
});

it('keeps the count identity that replaces the card’s count(„) === count(“)', () => {
Expand All@@ -289,11 +294,12 @@ describe('objectui#3876 — de pack closes „ with “ and not with a straight
// 53 / 53 / 0 after objectui#5232 added
// `console.objectView.viewConfigPermissionDenied`; 54 / 54 / 0 after
// objectui#6301 added `packagedAutomation.cloneCreated`; 55 / 55 / 0 after
// objectui#6655 added `timeline.unsupported.objectBoundGantt`. `rdq` staying
// at 0 is the load-bearing half: each new value added a MATCHED „…“ pair,
// not a stray closer that would have made `close === open` true for the
// wrong reason.
expect({ open, close, rdq }).toEqual({ open: 55, close: 55, rdq: 0 });
// objectui#6655 added `timeline.unsupported.objectBoundGantt`; 58 / 58 / 0
// after objectui#7149 added the two quoted `ActivityTimeline` sentences
// (three spans between them). `rdq` staying at 0 is the load-bearing half:
// each new value added a MATCHED „…“ pair, not a stray closer that would
// have made `close === open` true for the wrong reason.
expect({ open, close, rdq }).toEqual({ open: 58, close: 58, rdq: 0 });
// The durable shape: every „ closed by a “, every surplus “ an English
// opener answered by a ”. Survived translating the two English values.
expect(close).toBe(open + rdq);
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/ar.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -960,6 +960,19 @@ const ar = {
tasksOnly: "المهام فقط",
leaveCommentPlaceholder: "اترك تعليقاً… (Ctrl+Enter للإرسال)",
noActivity: "لا يوجد نشاط مسجل",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'الكل',
createsFilter: 'عمليات الإنشاء',
deletesFilter: 'عمليات الحذف',
statusChangesFilter: 'تغييرات الحالة',
activityEmptyValue: '(فارغ)',
activityFieldChanged: 'غيّر {{field}} من "{{old}}" إلى "{{new}}"',
activityCreated: 'أنشأ هذا السجل',
activityDeleted: 'حذف هذا السجل',
activityStatusChanged: 'غيّر الحالة إلى "{{value}}"',
activityUpdated: 'حدّث السجل',
loadMore: "تحميل المزيد",
edited: "(معدل)",
via: "عبر {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/de.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -954,6 +954,19 @@ const de = {
tasksOnly: "Nur Aufgaben",
leaveCommentPlaceholder: "Kommentar hinterlassen… (Strg+Enter zum Senden)",
noActivity: "Keine Aktivitäten aufgezeichnet",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'Alle',
createsFilter: 'Erstellungen',
deletesFilter: 'Löschungen',
statusChangesFilter: 'Statusänderungen',
activityEmptyValue: '(leer)',
activityFieldChanged: '{{field}} von „{{old}}“ zu „{{new}}“ geändert',
activityCreated: 'Diesen Datensatz erstellt',
activityDeleted: 'Diesen Datensatz gelöscht',
activityStatusChanged: 'Status zu „{{value}}“ geändert',
activityUpdated: 'Datensatz aktualisiert',
loadMore: "Mehr laden",
edited: "(bearbeitet)",
via: "über {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/en.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -1168,6 +1168,19 @@ const en = {
tasksOnly: 'Tasks Only',
leaveCommentPlaceholder: 'Leave a comment… (Ctrl+Enter to submit)',
noActivity: 'No activity recorded',
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'All',
createsFilter: 'Creates',
deletesFilter: 'Deletes',
statusChangesFilter: 'Status Changes',
activityEmptyValue: '(empty)',
activityFieldChanged: 'Changed {{field}} from "{{old}}" to "{{new}}"',
activityCreated: 'Created this record',
activityDeleted: 'Deleted this record',
activityStatusChanged: 'Changed status to "{{value}}"',
activityUpdated: 'Updated record',
loadMore: 'Load more',
edited: '(edited)',
via: 'via {{source}}',
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/es.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -958,6 +958,19 @@ const es = {
tasksOnly: "Solo tareas",
leaveCommentPlaceholder: "Deja un comentario… (Ctrl+Enter para enviar)",
noActivity: "Sin actividad registrada",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'Todo',
createsFilter: 'Creaciones',
deletesFilter: 'Eliminaciones',
statusChangesFilter: 'Cambios de estado',
activityEmptyValue: '(vacío)',
activityFieldChanged: 'Cambió {{field}} de "{{old}}" a "{{new}}"',
activityCreated: 'Creó este registro',
activityDeleted: 'Eliminó este registro',
activityStatusChanged: 'Cambió el estado a "{{value}}"',
activityUpdated: 'Actualizó el registro',
loadMore: "Cargar más",
edited: "(editado)",
via: "vía {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/fr.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -956,6 +956,19 @@ const fr = {
tasksOnly: "Tâches uniquement",
leaveCommentPlaceholder: "Laisser un commentaire… (Ctrl+Entrée pour envoyer)",
noActivity: "Aucune activité enregistrée",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'Tout',
createsFilter: 'Créations',
deletesFilter: 'Suppressions',
statusChangesFilter: 'Changements de statut',
activityEmptyValue: '(vide)',
activityFieldChanged: '{{field}} modifié de « {{old}} » à « {{new}} »',
activityCreated: 'A créé cet enregistrement',
activityDeleted: 'A supprimé cet enregistrement',
activityStatusChanged: 'A changé le statut en « {{value}} »',
activityUpdated: 'A mis à jour l\'enregistrement',
loadMore: "Charger plus",
edited: "(modifié)",
via: "via {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/ja.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -965,6 +965,19 @@ const ja = {
tasksOnly: "タスクのみ",
leaveCommentPlaceholder: "コメントを入力… (Ctrl+Enterで送信)",
noActivity: "アクティビティの記録なし",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'すべて',
createsFilter: '作成',
deletesFilter: '削除',
statusChangesFilter: 'ステータス変更',
activityEmptyValue: '(空)',
activityFieldChanged: '{{field}} を「{{old}}」から「{{new}}」に変更しました',
activityCreated: 'このレコードを作成しました',
activityDeleted: 'このレコードを削除しました',
activityStatusChanged: 'ステータスを「{{value}}」に変更しました',
activityUpdated: 'レコードを更新しました',
loadMore: "さらに読み込む",
edited: "(編集済み)",
via: "{{source}} 経由",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/ko.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -954,6 +954,19 @@ const ko = {
tasksOnly: "작업만",
leaveCommentPlaceholder: "댓글 남기기… (Ctrl+Enter로 제출)",
noActivity: "기록된 활동 없음",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: '전체',
createsFilter: '생성',
deletesFilter: '삭제',
statusChangesFilter: '상태 변경',
activityEmptyValue: '(비어 있음)',
activityFieldChanged: '{{field}}을(를) "{{old}}"에서 "{{new}}"(으)로 변경했습니다',
activityCreated: '이 레코드를 만들었습니다',
activityDeleted: '이 레코드를 삭제했습니다',
activityStatusChanged: '상태를 "{{value}}"(으)로 변경했습니다',
activityUpdated: '레코드를 업데이트했습니다',
loadMore: "더 보기",
edited: "(수정됨)",
via: "{{source}} 통해",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/pt.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -955,6 +955,19 @@ const pt = {
tasksOnly: "Apenas tarefas",
leaveCommentPlaceholder: "Deixar um comentário… (Ctrl+Enter para enviar)",
noActivity: "Nenhuma atividade registrada",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'Tudo',
createsFilter: 'Criações',
deletesFilter: 'Exclusões',
statusChangesFilter: 'Alterações de status',
activityEmptyValue: '(vazio)',
activityFieldChanged: 'Alterou {{field}} de "{{old}}" para "{{new}}"',
activityCreated: 'Criou este registro',
activityDeleted: 'Excluiu este registro',
activityStatusChanged: 'Alterou o status para "{{value}}"',
activityUpdated: 'Atualizou o registro',
loadMore: "Carregar mais",
edited: "(editado)",
via: "via {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/ru.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -973,6 +973,19 @@ const ru = {
tasksOnly: "Только задачи",
leaveCommentPlaceholder: "Оставить комментарий… (Ctrl+Enter для отправки)",
noActivity: "Нет зарегистрированной активности",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'Все',
createsFilter: 'Создания',
deletesFilter: 'Удаления',
statusChangesFilter: 'Изменения статуса',
activityEmptyValue: '(пусто)',
activityFieldChanged: 'Изменено поле {{field}} с «{{old}}» на «{{new}}»',
activityCreated: 'Создал эту запись',
activityDeleted: 'Удалил эту запись',
activityStatusChanged: 'Изменил статус на «{{value}}»',
activityUpdated: 'Обновил запись',
loadMore: "Загрузить ещё",
edited: "(изменено)",
via: "через {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/zh.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -1057,6 +1057,19 @@ const zh = {
tasksOnly: '仅任务',
leaveCommentPlaceholder: '留下评论… (Ctrl+Enter 提交)',
noActivity: '暂无活动记录',
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: '全部',
createsFilter: '创建',
deletesFilter: '删除',
statusChangesFilter: '状态变更',
activityEmptyValue: '(空)',
activityFieldChanged: '将 {{field}} 从“{{old}}”改为“{{new}}”',
activityCreated: '创建了此记录',
activityDeleted: '删除了此记录',
activityStatusChanged: '将状态改为“{{value}}”',
activityUpdated: '更新了记录',
loadMore: '加载更多',
edited: '(已编辑)',
via: '通过 {{source}}',
Expand Down
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .changeset/7149-activity-timeline-remaining-literals.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
---
'@object-ui/plugin-detail': patch
'@object-ui/i18n': patch
---

`ActivityTimeline` speaks the session locale — the other 18 literals
(objectui#7149).

objectui#7142 gave this component its first `t()` call (the empty-state title)
and filed the sweep that found the rest. Until now a zh activity tab read
`"Activity(0)暂无活动记录"`: one translated string in a component that was
otherwise entirely English.

All 18 now resolve from the ten packs, in three groups:

- **Relative timestamps and the card title** (`just now`, `{{count}}m/h/d ago`,
`Activity`) — these render on *every* activity tab. All five were a pure
lookup swap: the `en` pack value was already byte-identical to the literal,
and the sibling `RecordActivityTimeline` already used the same keys.
- **The `formatFieldChange` sentences** — assembled in code, so they needed new
keys *with* interpolation holes rather than a lookup. Same reachability as the
timestamps: they render for any entry whose optional `description` is absent.
The quotes live inside each pack's value, so every locale punctuates its own
way (de `„…“`, zh `“…”`, ja `「…」`, fr/ru `«…»`).
- **The six filter chips and the chip group's accessible name** — reachable only
through the published export, since no host in this repo passes `filterable`.

Ten new `detail.*` keys across all ten packs (no inline `defaultValue` —
objectui#3517), mirrored byte-for-byte into `DETAIL_DEFAULT_TRANSLATIONS` so a
provider-less host still reads English rather than a raw key.

One deliberate English copy change: the chip group's `aria-label` was
`"Activity type filter"` and now resolves `detail.filterActivity`
(`"Filter activity"`) — the key `RecordActivityTimeline` already uses for the
accessible name of its own activity filter, so one control does not carry two
names across two components.

Also drops the unused `Filter` import (a pre-existing eslint warning).
20 changes: 13 additions & 7 deletions packages/i18n/src/__tests__/de-quote-pairing-3876.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -268,8 +268,13 @@ describe('objectui#3876 — de pack closes „ with “ and not with a straight
// 55 once objectui#6655 added `timeline.unsupported.objectBoundGantt`, the
// object-bound timeline's refusal of `variant: gantt`, which names the
// refused variant — „gantt“, a literal span, because the quoted thing is an
// authoring value the author typed rather than data the runtime filled in.
expect(okSpans, 'correctly paired spans').toBe(55);
// authoring value the author typed rather than data the runtime filled in,
// 58 once objectui#7149 gave `ActivityTimeline`'s assembled sentences pack
// keys: `detail.activityFieldChanged` quotes the OLD and NEW field values
// („{{old}}“ / „{{new}}“, two spans in one value, like `navigationSync.
// renamedPage` above) and `detail.activityStatusChanged` the new status
// („{{value}}“) — three interpolated spans, all runtime data.
expect(okSpans, 'correctly paired spans').toBe(58);
});

it('keeps the count identity that replaces the card’s count(„) === count(“)', () => {
Expand All@@ -289,11 +294,12 @@ describe('objectui#3876 — de pack closes „ with “ and not with a straight
// 53 / 53 / 0 after objectui#5232 added
// `console.objectView.viewConfigPermissionDenied`; 54 / 54 / 0 after
// objectui#6301 added `packagedAutomation.cloneCreated`; 55 / 55 / 0 after
// objectui#6655 added `timeline.unsupported.objectBoundGantt`. `rdq` staying
// at 0 is the load-bearing half: each new value added a MATCHED „…“ pair,
// not a stray closer that would have made `close === open` true for the
// wrong reason.
expect({ open, close, rdq }).toEqual({ open: 55, close: 55, rdq: 0 });
// objectui#6655 added `timeline.unsupported.objectBoundGantt`; 58 / 58 / 0
// after objectui#7149 added the two quoted `ActivityTimeline` sentences
// (three spans between them). `rdq` staying at 0 is the load-bearing half:
// each new value added a MATCHED „…“ pair, not a stray closer that would
// have made `close === open` true for the wrong reason.
expect({ open, close, rdq }).toEqual({ open: 58, close: 58, rdq: 0 });
// The durable shape: every „ closed by a “, every surplus “ an English
// opener answered by a ”. Survived translating the two English values.
expect(close).toBe(open + rdq);
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/ar.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -960,6 +960,19 @@ const ar = {
tasksOnly: "المهام فقط",
leaveCommentPlaceholder: "اترك تعليقاً… (Ctrl+Enter للإرسال)",
noActivity: "لا يوجد نشاط مسجل",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'الكل',
createsFilter: 'عمليات الإنشاء',
deletesFilter: 'عمليات الحذف',
statusChangesFilter: 'تغييرات الحالة',
activityEmptyValue: '(فارغ)',
activityFieldChanged: 'غيّر {{field}} من "{{old}}" إلى "{{new}}"',
activityCreated: 'أنشأ هذا السجل',
activityDeleted: 'حذف هذا السجل',
activityStatusChanged: 'غيّر الحالة إلى "{{value}}"',
activityUpdated: 'حدّث السجل',
loadMore: "تحميل المزيد",
edited: "(معدل)",
via: "عبر {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/de.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -954,6 +954,19 @@ const de = {
tasksOnly: "Nur Aufgaben",
leaveCommentPlaceholder: "Kommentar hinterlassen… (Strg+Enter zum Senden)",
noActivity: "Keine Aktivitäten aufgezeichnet",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'Alle',
createsFilter: 'Erstellungen',
deletesFilter: 'Löschungen',
statusChangesFilter: 'Statusänderungen',
activityEmptyValue: '(leer)',
activityFieldChanged: '{{field}} von „{{old}}“ zu „{{new}}“ geändert',
activityCreated: 'Diesen Datensatz erstellt',
activityDeleted: 'Diesen Datensatz gelöscht',
activityStatusChanged: 'Status zu „{{value}}“ geändert',
activityUpdated: 'Datensatz aktualisiert',
loadMore: "Mehr laden",
edited: "(bearbeitet)",
via: "über {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/en.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -1168,6 +1168,19 @@ const en = {
tasksOnly: 'Tasks Only',
leaveCommentPlaceholder: 'Leave a comment… (Ctrl+Enter to submit)',
noActivity: 'No activity recorded',
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'All',
createsFilter: 'Creates',
deletesFilter: 'Deletes',
statusChangesFilter: 'Status Changes',
activityEmptyValue: '(empty)',
activityFieldChanged: 'Changed {{field}} from "{{old}}" to "{{new}}"',
activityCreated: 'Created this record',
activityDeleted: 'Deleted this record',
activityStatusChanged: 'Changed status to "{{value}}"',
activityUpdated: 'Updated record',
loadMore: 'Load more',
edited: '(edited)',
via: 'via {{source}}',
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/es.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -958,6 +958,19 @@ const es = {
tasksOnly: "Solo tareas",
leaveCommentPlaceholder: "Deja un comentario… (Ctrl+Enter para enviar)",
noActivity: "Sin actividad registrada",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'Todo',
createsFilter: 'Creaciones',
deletesFilter: 'Eliminaciones',
statusChangesFilter: 'Cambios de estado',
activityEmptyValue: '(vacío)',
activityFieldChanged: 'Cambió {{field}} de "{{old}}" a "{{new}}"',
activityCreated: 'Creó este registro',
activityDeleted: 'Eliminó este registro',
activityStatusChanged: 'Cambió el estado a "{{value}}"',
activityUpdated: 'Actualizó el registro',
loadMore: "Cargar más",
edited: "(editado)",
via: "vía {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/fr.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -956,6 +956,19 @@ const fr = {
tasksOnly: "Tâches uniquement",
leaveCommentPlaceholder: "Laisser un commentaire… (Ctrl+Entrée pour envoyer)",
noActivity: "Aucune activité enregistrée",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'Tout',
createsFilter: 'Créations',
deletesFilter: 'Suppressions',
statusChangesFilter: 'Changements de statut',
activityEmptyValue: '(vide)',
activityFieldChanged: '{{field}} modifié de « {{old}} » à « {{new}} »',
activityCreated: 'A créé cet enregistrement',
activityDeleted: 'A supprimé cet enregistrement',
activityStatusChanged: 'A changé le statut en « {{value}} »',
activityUpdated: 'A mis à jour l\'enregistrement',
loadMore: "Charger plus",
edited: "(modifié)",
via: "via {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/ja.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -965,6 +965,19 @@ const ja = {
tasksOnly: "タスクのみ",
leaveCommentPlaceholder: "コメントを入力… (Ctrl+Enterで送信)",
noActivity: "アクティビティの記録なし",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'すべて',
createsFilter: '作成',
deletesFilter: '削除',
statusChangesFilter: 'ステータス変更',
activityEmptyValue: '(空)',
activityFieldChanged: '{{field}} を「{{old}}」から「{{new}}」に変更しました',
activityCreated: 'このレコードを作成しました',
activityDeleted: 'このレコードを削除しました',
activityStatusChanged: 'ステータスを「{{value}}」に変更しました',
activityUpdated: 'レコードを更新しました',
loadMore: "さらに読み込む",
edited: "(編集済み)",
via: "{{source}} 経由",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/ko.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -954,6 +954,19 @@ const ko = {
tasksOnly: "작업만",
leaveCommentPlaceholder: "댓글 남기기… (Ctrl+Enter로 제출)",
noActivity: "기록된 활동 없음",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: '전체',
createsFilter: '생성',
deletesFilter: '삭제',
statusChangesFilter: '상태 변경',
activityEmptyValue: '(비어 있음)',
activityFieldChanged: '{{field}}을(를) "{{old}}"에서 "{{new}}"(으)로 변경했습니다',
activityCreated: '이 레코드를 만들었습니다',
activityDeleted: '이 레코드를 삭제했습니다',
activityStatusChanged: '상태를 "{{value}}"(으)로 변경했습니다',
activityUpdated: '레코드를 업데이트했습니다',
loadMore: "더 보기",
edited: "(수정됨)",
via: "{{source}} 통해",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/pt.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -955,6 +955,19 @@ const pt = {
tasksOnly: "Apenas tarefas",
leaveCommentPlaceholder: "Deixar um comentário… (Ctrl+Enter para enviar)",
noActivity: "Nenhuma atividade registrada",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'Tudo',
createsFilter: 'Criações',
deletesFilter: 'Exclusões',
statusChangesFilter: 'Alterações de status',
activityEmptyValue: '(vazio)',
activityFieldChanged: 'Alterou {{field}} de "{{old}}" para "{{new}}"',
activityCreated: 'Criou este registro',
activityDeleted: 'Excluiu este registro',
activityStatusChanged: 'Alterou o status para "{{value}}"',
activityUpdated: 'Atualizou o registro',
loadMore: "Carregar mais",
edited: "(editado)",
via: "via {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/ru.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -973,6 +973,19 @@ const ru = {
tasksOnly: "Только задачи",
leaveCommentPlaceholder: "Оставить комментарий… (Ctrl+Enter для отправки)",
noActivity: "Нет зарегистрированной активности",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'Все',
createsFilter: 'Создания',
deletesFilter: 'Удаления',
statusChangesFilter: 'Изменения статуса',
activityEmptyValue: '(пусто)',
activityFieldChanged: 'Изменено поле {{field}} с «{{old}}» на «{{new}}»',
activityCreated: 'Создал эту запись',
activityDeleted: 'Удалил эту запись',
activityStatusChanged: 'Изменил статус на «{{value}}»',
activityUpdated: 'Обновил запись',
loadMore: "Загрузить ещё",
edited: "(изменено)",
via: "через {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/zh.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -1057,6 +1057,19 @@ const zh = {
tasksOnly: '仅任务',
leaveCommentPlaceholder: '留下评论… (Ctrl+Enter 提交)',
noActivity: '暂无活动记录',
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: '全部',
createsFilter: '创建',
deletesFilter: '删除',
statusChangesFilter: '状态变更',
activityEmptyValue: '(空)',
activityFieldChanged: '将 {{field}} 从“{{old}}”改为“{{new}}”',
activityCreated: '创建了此记录',
activityDeleted: '删除了此记录',
activityStatusChanged: '将状态改为“{{value}}”',
activityUpdated: '更新了记录',
loadMore: '加载更多',
edited: '(已编辑)',
via: '通过 {{source}}',
Expand Down
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .changeset/7149-activity-timeline-remaining-literals.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
---
'@object-ui/plugin-detail': patch
'@object-ui/i18n': patch
---

`ActivityTimeline` speaks the session locale — the other 18 literals
(objectui#7149).

objectui#7142 gave this component its first `t()` call (the empty-state title)
and filed the sweep that found the rest. Until now a zh activity tab read
`"Activity(0)暂无活动记录"`: one translated string in a component that was
otherwise entirely English.

All 18 now resolve from the ten packs, in three groups:

- **Relative timestamps and the card title** (`just now`, `{{count}}m/h/d ago`,
`Activity`) — these render on *every* activity tab. All five were a pure
lookup swap: the `en` pack value was already byte-identical to the literal,
and the sibling `RecordActivityTimeline` already used the same keys.
- **The `formatFieldChange` sentences** — assembled in code, so they needed new
keys *with* interpolation holes rather than a lookup. Same reachability as the
timestamps: they render for any entry whose optional `description` is absent.
The quotes live inside each pack's value, so every locale punctuates its own
way (de `„…“`, zh `“…”`, ja `「…」`, fr/ru `«…»`).
- **The six filter chips and the chip group's accessible name** — reachable only
through the published export, since no host in this repo passes `filterable`.

Ten new `detail.*` keys across all ten packs (no inline `defaultValue` —
objectui#3517), mirrored byte-for-byte into `DETAIL_DEFAULT_TRANSLATIONS` so a
provider-less host still reads English rather than a raw key.

One deliberate English copy change: the chip group's `aria-label` was
`"Activity type filter"` and now resolves `detail.filterActivity`
(`"Filter activity"`) — the key `RecordActivityTimeline` already uses for the
accessible name of its own activity filter, so one control does not carry two
names across two components.

Also drops the unused `Filter` import (a pre-existing eslint warning).
20 changes: 13 additions & 7 deletions packages/i18n/src/__tests__/de-quote-pairing-3876.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -268,8 +268,13 @@ describe('objectui#3876 — de pack closes „ with “ and not with a straight
// 55 once objectui#6655 added `timeline.unsupported.objectBoundGantt`, the
// object-bound timeline's refusal of `variant: gantt`, which names the
// refused variant — „gantt“, a literal span, because the quoted thing is an
// authoring value the author typed rather than data the runtime filled in.
expect(okSpans, 'correctly paired spans').toBe(55);
// authoring value the author typed rather than data the runtime filled in,
// 58 once objectui#7149 gave `ActivityTimeline`'s assembled sentences pack
// keys: `detail.activityFieldChanged` quotes the OLD and NEW field values
// („{{old}}“ / „{{new}}“, two spans in one value, like `navigationSync.
// renamedPage` above) and `detail.activityStatusChanged` the new status
// („{{value}}“) — three interpolated spans, all runtime data.
expect(okSpans, 'correctly paired spans').toBe(58);
});

it('keeps the count identity that replaces the card’s count(„) === count(“)', () => {
Expand All@@ -289,11 +294,12 @@ describe('objectui#3876 — de pack closes „ with “ and not with a straight
// 53 / 53 / 0 after objectui#5232 added
// `console.objectView.viewConfigPermissionDenied`; 54 / 54 / 0 after
// objectui#6301 added `packagedAutomation.cloneCreated`; 55 / 55 / 0 after
// objectui#6655 added `timeline.unsupported.objectBoundGantt`. `rdq` staying
// at 0 is the load-bearing half: each new value added a MATCHED „…“ pair,
// not a stray closer that would have made `close === open` true for the
// wrong reason.
expect({ open, close, rdq }).toEqual({ open: 55, close: 55, rdq: 0 });
// objectui#6655 added `timeline.unsupported.objectBoundGantt`; 58 / 58 / 0
// after objectui#7149 added the two quoted `ActivityTimeline` sentences
// (three spans between them). `rdq` staying at 0 is the load-bearing half:
// each new value added a MATCHED „…“ pair, not a stray closer that would
// have made `close === open` true for the wrong reason.
expect({ open, close, rdq }).toEqual({ open: 58, close: 58, rdq: 0 });
// The durable shape: every „ closed by a “, every surplus “ an English
// opener answered by a ”. Survived translating the two English values.
expect(close).toBe(open + rdq);
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/ar.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -960,6 +960,19 @@ const ar = {
tasksOnly: "المهام فقط",
leaveCommentPlaceholder: "اترك تعليقاً… (Ctrl+Enter للإرسال)",
noActivity: "لا يوجد نشاط مسجل",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'الكل',
createsFilter: 'عمليات الإنشاء',
deletesFilter: 'عمليات الحذف',
statusChangesFilter: 'تغييرات الحالة',
activityEmptyValue: '(فارغ)',
activityFieldChanged: 'غيّر {{field}} من "{{old}}" إلى "{{new}}"',
activityCreated: 'أنشأ هذا السجل',
activityDeleted: 'حذف هذا السجل',
activityStatusChanged: 'غيّر الحالة إلى "{{value}}"',
activityUpdated: 'حدّث السجل',
loadMore: "تحميل المزيد",
edited: "(معدل)",
via: "عبر {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/de.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -954,6 +954,19 @@ const de = {
tasksOnly: "Nur Aufgaben",
leaveCommentPlaceholder: "Kommentar hinterlassen… (Strg+Enter zum Senden)",
noActivity: "Keine Aktivitäten aufgezeichnet",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'Alle',
createsFilter: 'Erstellungen',
deletesFilter: 'Löschungen',
statusChangesFilter: 'Statusänderungen',
activityEmptyValue: '(leer)',
activityFieldChanged: '{{field}} von „{{old}}“ zu „{{new}}“ geändert',
activityCreated: 'Diesen Datensatz erstellt',
activityDeleted: 'Diesen Datensatz gelöscht',
activityStatusChanged: 'Status zu „{{value}}“ geändert',
activityUpdated: 'Datensatz aktualisiert',
loadMore: "Mehr laden",
edited: "(bearbeitet)",
via: "über {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/en.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -1168,6 +1168,19 @@ const en = {
tasksOnly: 'Tasks Only',
leaveCommentPlaceholder: 'Leave a comment… (Ctrl+Enter to submit)',
noActivity: 'No activity recorded',
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'All',
createsFilter: 'Creates',
deletesFilter: 'Deletes',
statusChangesFilter: 'Status Changes',
activityEmptyValue: '(empty)',
activityFieldChanged: 'Changed {{field}} from "{{old}}" to "{{new}}"',
activityCreated: 'Created this record',
activityDeleted: 'Deleted this record',
activityStatusChanged: 'Changed status to "{{value}}"',
activityUpdated: 'Updated record',
loadMore: 'Load more',
edited: '(edited)',
via: 'via {{source}}',
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/es.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -958,6 +958,19 @@ const es = {
tasksOnly: "Solo tareas",
leaveCommentPlaceholder: "Deja un comentario… (Ctrl+Enter para enviar)",
noActivity: "Sin actividad registrada",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'Todo',
createsFilter: 'Creaciones',
deletesFilter: 'Eliminaciones',
statusChangesFilter: 'Cambios de estado',
activityEmptyValue: '(vacío)',
activityFieldChanged: 'Cambió {{field}} de "{{old}}" a "{{new}}"',
activityCreated: 'Creó este registro',
activityDeleted: 'Eliminó este registro',
activityStatusChanged: 'Cambió el estado a "{{value}}"',
activityUpdated: 'Actualizó el registro',
loadMore: "Cargar más",
edited: "(editado)",
via: "vía {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/fr.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -956,6 +956,19 @@ const fr = {
tasksOnly: "Tâches uniquement",
leaveCommentPlaceholder: "Laisser un commentaire… (Ctrl+Entrée pour envoyer)",
noActivity: "Aucune activité enregistrée",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'Tout',
createsFilter: 'Créations',
deletesFilter: 'Suppressions',
statusChangesFilter: 'Changements de statut',
activityEmptyValue: '(vide)',
activityFieldChanged: '{{field}} modifié de « {{old}} » à « {{new}} »',
activityCreated: 'A créé cet enregistrement',
activityDeleted: 'A supprimé cet enregistrement',
activityStatusChanged: 'A changé le statut en « {{value}} »',
activityUpdated: 'A mis à jour l\'enregistrement',
loadMore: "Charger plus",
edited: "(modifié)",
via: "via {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/ja.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -965,6 +965,19 @@ const ja = {
tasksOnly: "タスクのみ",
leaveCommentPlaceholder: "コメントを入力… (Ctrl+Enterで送信)",
noActivity: "アクティビティの記録なし",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'すべて',
createsFilter: '作成',
deletesFilter: '削除',
statusChangesFilter: 'ステータス変更',
activityEmptyValue: '(空)',
activityFieldChanged: '{{field}} を「{{old}}」から「{{new}}」に変更しました',
activityCreated: 'このレコードを作成しました',
activityDeleted: 'このレコードを削除しました',
activityStatusChanged: 'ステータスを「{{value}}」に変更しました',
activityUpdated: 'レコードを更新しました',
loadMore: "さらに読み込む",
edited: "(編集済み)",
via: "{{source}} 経由",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/ko.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -954,6 +954,19 @@ const ko = {
tasksOnly: "작업만",
leaveCommentPlaceholder: "댓글 남기기… (Ctrl+Enter로 제출)",
noActivity: "기록된 활동 없음",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: '전체',
createsFilter: '생성',
deletesFilter: '삭제',
statusChangesFilter: '상태 변경',
activityEmptyValue: '(비어 있음)',
activityFieldChanged: '{{field}}을(를) "{{old}}"에서 "{{new}}"(으)로 변경했습니다',
activityCreated: '이 레코드를 만들었습니다',
activityDeleted: '이 레코드를 삭제했습니다',
activityStatusChanged: '상태를 "{{value}}"(으)로 변경했습니다',
activityUpdated: '레코드를 업데이트했습니다',
loadMore: "더 보기",
edited: "(수정됨)",
via: "{{source}} 통해",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/pt.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -955,6 +955,19 @@ const pt = {
tasksOnly: "Apenas tarefas",
leaveCommentPlaceholder: "Deixar um comentário… (Ctrl+Enter para enviar)",
noActivity: "Nenhuma atividade registrada",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'Tudo',
createsFilter: 'Criações',
deletesFilter: 'Exclusões',
statusChangesFilter: 'Alterações de status',
activityEmptyValue: '(vazio)',
activityFieldChanged: 'Alterou {{field}} de "{{old}}" para "{{new}}"',
activityCreated: 'Criou este registro',
activityDeleted: 'Excluiu este registro',
activityStatusChanged: 'Alterou o status para "{{value}}"',
activityUpdated: 'Atualizou o registro',
loadMore: "Carregar mais",
edited: "(editado)",
via: "via {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/ru.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -973,6 +973,19 @@ const ru = {
tasksOnly: "Только задачи",
leaveCommentPlaceholder: "Оставить комментарий… (Ctrl+Enter для отправки)",
noActivity: "Нет зарегистрированной активности",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'Все',
createsFilter: 'Создания',
deletesFilter: 'Удаления',
statusChangesFilter: 'Изменения статуса',
activityEmptyValue: '(пусто)',
activityFieldChanged: 'Изменено поле {{field}} с «{{old}}» на «{{new}}»',
activityCreated: 'Создал эту запись',
activityDeleted: 'Удалил эту запись',
activityStatusChanged: 'Изменил статус на «{{value}}»',
activityUpdated: 'Обновил запись',
loadMore: "Загрузить ещё",
edited: "(изменено)",
via: "через {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/zh.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -1057,6 +1057,19 @@ const zh = {
tasksOnly: '仅任务',
leaveCommentPlaceholder: '留下评论… (Ctrl+Enter 提交)',
noActivity: '暂无活动记录',
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: '全部',
createsFilter: '创建',
deletesFilter: '删除',
statusChangesFilter: '状态变更',
activityEmptyValue: '(空)',
activityFieldChanged: '将 {{field}} 从“{{old}}”改为“{{new}}”',
activityCreated: '创建了此记录',
activityDeleted: '删除了此记录',
activityStatusChanged: '将状态改为“{{value}}”',
activityUpdated: '更新了记录',
loadMore: '加载更多',
edited: '(已编辑)',
via: '通过 {{source}}',
Expand Down
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .changeset/7149-activity-timeline-remaining-literals.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
---
'@object-ui/plugin-detail': patch
'@object-ui/i18n': patch
---

`ActivityTimeline` speaks the session locale — the other 18 literals
(objectui#7149).

objectui#7142 gave this component its first `t()` call (the empty-state title)
and filed the sweep that found the rest. Until now a zh activity tab read
`"Activity(0)暂无活动记录"`: one translated string in a component that was
otherwise entirely English.

All 18 now resolve from the ten packs, in three groups:

- **Relative timestamps and the card title** (`just now`, `{{count}}m/h/d ago`,
`Activity`) — these render on *every* activity tab. All five were a pure
lookup swap: the `en` pack value was already byte-identical to the literal,
and the sibling `RecordActivityTimeline` already used the same keys.
- **The `formatFieldChange` sentences** — assembled in code, so they needed new
keys *with* interpolation holes rather than a lookup. Same reachability as the
timestamps: they render for any entry whose optional `description` is absent.
The quotes live inside each pack's value, so every locale punctuates its own
way (de `„…“`, zh `“…”`, ja `「…」`, fr/ru `«…»`).
- **The six filter chips and the chip group's accessible name** — reachable only
through the published export, since no host in this repo passes `filterable`.

Ten new `detail.*` keys across all ten packs (no inline `defaultValue` —
objectui#3517), mirrored byte-for-byte into `DETAIL_DEFAULT_TRANSLATIONS` so a
provider-less host still reads English rather than a raw key.

One deliberate English copy change: the chip group's `aria-label` was
`"Activity type filter"` and now resolves `detail.filterActivity`
(`"Filter activity"`) — the key `RecordActivityTimeline` already uses for the
accessible name of its own activity filter, so one control does not carry two
names across two components.

Also drops the unused `Filter` import (a pre-existing eslint warning).
20 changes: 13 additions & 7 deletions packages/i18n/src/__tests__/de-quote-pairing-3876.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -268,8 +268,13 @@ describe('objectui#3876 — de pack closes „ with “ and not with a straight
// 55 once objectui#6655 added `timeline.unsupported.objectBoundGantt`, the
// object-bound timeline's refusal of `variant: gantt`, which names the
// refused variant — „gantt“, a literal span, because the quoted thing is an
// authoring value the author typed rather than data the runtime filled in.
expect(okSpans, 'correctly paired spans').toBe(55);
// authoring value the author typed rather than data the runtime filled in,
// 58 once objectui#7149 gave `ActivityTimeline`'s assembled sentences pack
// keys: `detail.activityFieldChanged` quotes the OLD and NEW field values
// („{{old}}“ / „{{new}}“, two spans in one value, like `navigationSync.
// renamedPage` above) and `detail.activityStatusChanged` the new status
// („{{value}}“) — three interpolated spans, all runtime data.
expect(okSpans, 'correctly paired spans').toBe(58);
});

it('keeps the count identity that replaces the card’s count(„) === count(“)', () => {
Expand All@@ -289,11 +294,12 @@ describe('objectui#3876 — de pack closes „ with “ and not with a straight
// 53 / 53 / 0 after objectui#5232 added
// `console.objectView.viewConfigPermissionDenied`; 54 / 54 / 0 after
// objectui#6301 added `packagedAutomation.cloneCreated`; 55 / 55 / 0 after
// objectui#6655 added `timeline.unsupported.objectBoundGantt`. `rdq` staying
// at 0 is the load-bearing half: each new value added a MATCHED „…“ pair,
// not a stray closer that would have made `close === open` true for the
// wrong reason.
expect({ open, close, rdq }).toEqual({ open: 55, close: 55, rdq: 0 });
// objectui#6655 added `timeline.unsupported.objectBoundGantt`; 58 / 58 / 0
// after objectui#7149 added the two quoted `ActivityTimeline` sentences
// (three spans between them). `rdq` staying at 0 is the load-bearing half:
// each new value added a MATCHED „…“ pair, not a stray closer that would
// have made `close === open` true for the wrong reason.
expect({ open, close, rdq }).toEqual({ open: 58, close: 58, rdq: 0 });
// The durable shape: every „ closed by a “, every surplus “ an English
// opener answered by a ”. Survived translating the two English values.
expect(close).toBe(open + rdq);
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/ar.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -960,6 +960,19 @@ const ar = {
tasksOnly: "المهام فقط",
leaveCommentPlaceholder: "اترك تعليقاً… (Ctrl+Enter للإرسال)",
noActivity: "لا يوجد نشاط مسجل",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'الكل',
createsFilter: 'عمليات الإنشاء',
deletesFilter: 'عمليات الحذف',
statusChangesFilter: 'تغييرات الحالة',
activityEmptyValue: '(فارغ)',
activityFieldChanged: 'غيّر {{field}} من "{{old}}" إلى "{{new}}"',
activityCreated: 'أنشأ هذا السجل',
activityDeleted: 'حذف هذا السجل',
activityStatusChanged: 'غيّر الحالة إلى "{{value}}"',
activityUpdated: 'حدّث السجل',
loadMore: "تحميل المزيد",
edited: "(معدل)",
via: "عبر {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/de.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -954,6 +954,19 @@ const de = {
tasksOnly: "Nur Aufgaben",
leaveCommentPlaceholder: "Kommentar hinterlassen… (Strg+Enter zum Senden)",
noActivity: "Keine Aktivitäten aufgezeichnet",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'Alle',
createsFilter: 'Erstellungen',
deletesFilter: 'Löschungen',
statusChangesFilter: 'Statusänderungen',
activityEmptyValue: '(leer)',
activityFieldChanged: '{{field}} von „{{old}}“ zu „{{new}}“ geändert',
activityCreated: 'Diesen Datensatz erstellt',
activityDeleted: 'Diesen Datensatz gelöscht',
activityStatusChanged: 'Status zu „{{value}}“ geändert',
activityUpdated: 'Datensatz aktualisiert',
loadMore: "Mehr laden",
edited: "(bearbeitet)",
via: "über {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/en.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -1168,6 +1168,19 @@ const en = {
tasksOnly: 'Tasks Only',
leaveCommentPlaceholder: 'Leave a comment… (Ctrl+Enter to submit)',
noActivity: 'No activity recorded',
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'All',
createsFilter: 'Creates',
deletesFilter: 'Deletes',
statusChangesFilter: 'Status Changes',
activityEmptyValue: '(empty)',
activityFieldChanged: 'Changed {{field}} from "{{old}}" to "{{new}}"',
activityCreated: 'Created this record',
activityDeleted: 'Deleted this record',
activityStatusChanged: 'Changed status to "{{value}}"',
activityUpdated: 'Updated record',
loadMore: 'Load more',
edited: '(edited)',
via: 'via {{source}}',
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/es.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -958,6 +958,19 @@ const es = {
tasksOnly: "Solo tareas",
leaveCommentPlaceholder: "Deja un comentario… (Ctrl+Enter para enviar)",
noActivity: "Sin actividad registrada",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'Todo',
createsFilter: 'Creaciones',
deletesFilter: 'Eliminaciones',
statusChangesFilter: 'Cambios de estado',
activityEmptyValue: '(vacío)',
activityFieldChanged: 'Cambió {{field}} de "{{old}}" a "{{new}}"',
activityCreated: 'Creó este registro',
activityDeleted: 'Eliminó este registro',
activityStatusChanged: 'Cambió el estado a "{{value}}"',
activityUpdated: 'Actualizó el registro',
loadMore: "Cargar más",
edited: "(editado)",
via: "vía {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/fr.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -956,6 +956,19 @@ const fr = {
tasksOnly: "Tâches uniquement",
leaveCommentPlaceholder: "Laisser un commentaire… (Ctrl+Entrée pour envoyer)",
noActivity: "Aucune activité enregistrée",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'Tout',
createsFilter: 'Créations',
deletesFilter: 'Suppressions',
statusChangesFilter: 'Changements de statut',
activityEmptyValue: '(vide)',
activityFieldChanged: '{{field}} modifié de « {{old}} » à « {{new}} »',
activityCreated: 'A créé cet enregistrement',
activityDeleted: 'A supprimé cet enregistrement',
activityStatusChanged: 'A changé le statut en « {{value}} »',
activityUpdated: 'A mis à jour l\'enregistrement',
loadMore: "Charger plus",
edited: "(modifié)",
via: "via {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/ja.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -965,6 +965,19 @@ const ja = {
tasksOnly: "タスクのみ",
leaveCommentPlaceholder: "コメントを入力… (Ctrl+Enterで送信)",
noActivity: "アクティビティの記録なし",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'すべて',
createsFilter: '作成',
deletesFilter: '削除',
statusChangesFilter: 'ステータス変更',
activityEmptyValue: '(空)',
activityFieldChanged: '{{field}} を「{{old}}」から「{{new}}」に変更しました',
activityCreated: 'このレコードを作成しました',
activityDeleted: 'このレコードを削除しました',
activityStatusChanged: 'ステータスを「{{value}}」に変更しました',
activityUpdated: 'レコードを更新しました',
loadMore: "さらに読み込む",
edited: "(編集済み)",
via: "{{source}} 経由",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/ko.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -954,6 +954,19 @@ const ko = {
tasksOnly: "작업만",
leaveCommentPlaceholder: "댓글 남기기… (Ctrl+Enter로 제출)",
noActivity: "기록된 활동 없음",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: '전체',
createsFilter: '생성',
deletesFilter: '삭제',
statusChangesFilter: '상태 변경',
activityEmptyValue: '(비어 있음)',
activityFieldChanged: '{{field}}을(를) "{{old}}"에서 "{{new}}"(으)로 변경했습니다',
activityCreated: '이 레코드를 만들었습니다',
activityDeleted: '이 레코드를 삭제했습니다',
activityStatusChanged: '상태를 "{{value}}"(으)로 변경했습니다',
activityUpdated: '레코드를 업데이트했습니다',
loadMore: "더 보기",
edited: "(수정됨)",
via: "{{source}} 통해",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/pt.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -955,6 +955,19 @@ const pt = {
tasksOnly: "Apenas tarefas",
leaveCommentPlaceholder: "Deixar um comentário… (Ctrl+Enter para enviar)",
noActivity: "Nenhuma atividade registrada",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'Tudo',
createsFilter: 'Criações',
deletesFilter: 'Exclusões',
statusChangesFilter: 'Alterações de status',
activityEmptyValue: '(vazio)',
activityFieldChanged: 'Alterou {{field}} de "{{old}}" para "{{new}}"',
activityCreated: 'Criou este registro',
activityDeleted: 'Excluiu este registro',
activityStatusChanged: 'Alterou o status para "{{value}}"',
activityUpdated: 'Atualizou o registro',
loadMore: "Carregar mais",
edited: "(editado)",
via: "via {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/ru.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -973,6 +973,19 @@ const ru = {
tasksOnly: "Только задачи",
leaveCommentPlaceholder: "Оставить комментарий… (Ctrl+Enter для отправки)",
noActivity: "Нет зарегистрированной активности",
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: 'Все',
createsFilter: 'Создания',
deletesFilter: 'Удаления',
statusChangesFilter: 'Изменения статуса',
activityEmptyValue: '(пусто)',
activityFieldChanged: 'Изменено поле {{field}} с «{{old}}» на «{{new}}»',
activityCreated: 'Создал эту запись',
activityDeleted: 'Удалил эту запись',
activityStatusChanged: 'Изменил статус на «{{value}}»',
activityUpdated: 'Обновил запись',
loadMore: "Загрузить ещё",
edited: "(изменено)",
via: "через {{source}}",
Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/src/locales/zh.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -1057,6 +1057,19 @@ const zh = {
tasksOnly: '仅任务',
leaveCommentPlaceholder: '留下评论… (Ctrl+Enter 提交)',
noActivity: '暂无活动记录',
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
// `detail.*` pack did not already name, and the `formatFieldChange`
// sentences, which are assembled in code and so need interpolation holes.
allFilter: '全部',
createsFilter: '创建',
deletesFilter: '删除',
statusChangesFilter: '状态变更',
activityEmptyValue: '(空)',
activityFieldChanged: '将 {{field}} 从“{{old}}”改为“{{new}}”',
activityCreated: '创建了此记录',
activityDeleted: '删除了此记录',
activityStatusChanged: '将状态改为“{{value}}”',
activityUpdated: '更新了记录',
loadMore: '加载更多',
edited: '(已编辑)',
via: '通过 {{source}}',
Expand Down
Loading
Loading