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
35 changes: 35 additions & 0 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -1436,6 +1436,41 @@ All 313 `@object-ui/fields` tests pass.

---

## 📦 Detail Page & Related List i18n (P1.15)

> **Goal:** Salesforce-style detail page enhancements: i18n for all detail page UI elements, improved empty value display, related list actions, and auto-discovery of related lists.

**i18n Integration:**
- [x] Add `detail.*` translation keys to all 11 locale files (en, zh, ja, de, fr, es, ar, ru, pt, ko)
- [x] `useDetailTranslation` safe wrapper hook with English fallback (follows existing useGridTranslation/useListViewTranslation pattern)
- [x] DetailView fully i18n-integrated (Back, Edit, Share, Delete, Duplicate, Export, View history, Record not found, Related heading, favorites, navigation)
- [x] DetailSection copy tooltip i18n via `useSectionTranslation`
Copy link

Copilot AI Mar 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ROADMAP.md references useSectionTranslation for DetailSection tooltip i18n, but the implementation uses useDetailTranslation and there is no useSectionTranslation in the repo. Please update this line to match the actual hook name to avoid misleading documentation.

Suggested change
- [x] DetailSection copy tooltip i18n via `useSectionTranslation`
- [x] DetailSection copy tooltip i18n via `useDetailTranslation`

Copilot uses AI. Check for mistakes.
- [x] RelatedList i18n-integrated (record counts, loading, empty state)
- [x] Add `'detail'` to `BUILTIN_KEYS` in `useObjectLabel.ts` to prevent namespace collision

**Empty Value Display:**
- [x] Replace hardcoded `-` with styled em-dash (`—`) using `text-muted-foreground/50 text-xs italic` for elegant empty state

**Related List Enhancements:**
- [x] Add `onNew` prop and "New" button to RelatedList header
- [x] Add `onViewAll` prop and "View All" button to RelatedList header
- [x] Record count uses singular/plural i18n keys

**Tests:**
- [x] 10 new RelatedList tests (title, record counts, empty state, New/View All buttons)
- [x] 2 new DetailView i18n fallback tests (Record not found text, Related heading)
- [x] Updated DetailSection tests for new empty value styling

**Remaining (future PRs):**
- [ ] Auto-discover related lists from objectSchema reference fields
- [ ] Tab layout (Details/Related/Activity) for detail page
- [ ] Related list row-level Edit/Delete quick actions
- [ ] Related list pagination, sorting, filtering
- [ ] Collapsible section groups
- [ ] Header highlight area with key fields

---

## 📚 Reference

- [CONTRIBUTING.md](./CONTRIBUTING.md) — Contribution guidelines
Expand Down
35 changes: 35 additions & 0 deletions packages/i18n/src/locales/ar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,41 @@ const ar = {
deleteCard: 'حذف بطاقة',
deleteColumn: 'حذف عمود',
},
detail: {
back: 'رجوع',
edit: 'تحرير',
editInline: 'تحرير مباشر',
save: 'حفظ',
saveChanges: 'حفظ التغييرات',
editFieldsInline: 'تحرير الحقول مباشرة',
share: 'مشاركة',
duplicate: 'نسخ',
export: 'تصدير',
viewHistory: 'عرض السجل',
delete: 'حذف',
moreActions: 'المزيد من الإجراءات',
addToFavorites: 'إضافة إلى المفضلة',
removeFromFavorites: 'إزالة من المفضلة',
previousRecord: 'السجل السابق',
nextRecord: 'السجل التالي',
recordOf: '{{current}} من {{total}}',
recordNotFound: 'لم يتم العثور على السجل',
recordNotFoundDescription: 'السجل الذي تبحث عنه غير موجود أو ربما تم حذفه.',
goBack: 'رجوع',
details: 'التفاصيل',
related: 'ذات صلة',
relatedRecords: '{{count}} سجلات',
relatedRecordOne: '{{count}} سجل',
noRelatedRecords: 'لا توجد سجلات ذات صلة',
loading: 'جاري التحميل...',
copyToClipboard: 'نسخ إلى الحافظة',
copied: 'تم النسخ!',
deleteConfirmation: 'هل أنت متأكد أنك تريد حذف هذا السجل؟',
editRecord: 'تحرير السجل',
viewAll: 'عرض الكل',
new: 'جديد',
emptyValue: '—',
},
chart: {
noData: 'لا تتوفر بيانات للرسم البياني',
loading: 'جاري تحميل الرسم البياني...',
Expand Down
35 changes: 35 additions & 0 deletions packages/i18n/src/locales/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,41 @@ const de = {
deleteCard: 'Karte löschen',
deleteColumn: 'Spalte löschen',
},
detail: {
back: 'Zurück',
edit: 'Bearbeiten',
editInline: 'Inline bearbeiten',
save: 'Speichern',
saveChanges: 'Änderungen speichern',
editFieldsInline: 'Felder inline bearbeiten',
share: 'Teilen',
duplicate: 'Duplizieren',
export: 'Exportieren',
viewHistory: 'Verlauf anzeigen',
delete: 'Löschen',
moreActions: 'Weitere Aktionen',
addToFavorites: 'Zu Favoriten hinzufügen',
removeFromFavorites: 'Aus Favoriten entfernen',
previousRecord: 'Vorheriger Datensatz',
nextRecord: 'Nächster Datensatz',
recordOf: '{{current}} von {{total}}',
recordNotFound: 'Datensatz nicht gefunden',
recordNotFoundDescription: 'Der gesuchte Datensatz existiert nicht oder wurde möglicherweise gelöscht.',
goBack: 'Zurück',
details: 'Details',
related: 'Verknüpft',
relatedRecords: '{{count}} Datensätze',
relatedRecordOne: '{{count}} Datensatz',
noRelatedRecords: 'Keine verknüpften Datensätze gefunden',
loading: 'Laden...',
copyToClipboard: 'In Zwischenablage kopieren',
copied: 'Kopiert!',
deleteConfirmation: 'Sind Sie sicher, dass Sie diesen Datensatz löschen möchten?',
editRecord: 'Datensatz bearbeiten',
viewAll: 'Alle anzeigen',
new: 'Neu',
emptyValue: '—',
},
chart: {
noData: 'Keine Diagrammdaten verfügbar',
loading: 'Diagramm wird geladen...',
Expand Down
35 changes: 35 additions & 0 deletions packages/i18n/src/locales/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,41 @@ const en = {
deleteCard: 'Delete card',
deleteColumn: 'Delete column',
},
detail: {
back: 'Back',
edit: 'Edit',
editInline: 'Edit inline',
save: 'Save',
saveChanges: 'Save changes',
editFieldsInline: 'Edit fields inline',
share: 'Share',
duplicate: 'Duplicate',
export: 'Export',
viewHistory: 'View history',
delete: 'Delete',
moreActions: 'More actions',
addToFavorites: 'Add to favorites',
removeFromFavorites: 'Remove from favorites',
previousRecord: 'Previous record',
nextRecord: 'Next record',
recordOf: '{{current}} of {{total}}',
recordNotFound: 'Record not found',
recordNotFoundDescription: 'The record you are looking for does not exist or may have been deleted.',
goBack: 'Go back',
details: 'Details',
related: 'Related',
relatedRecords: '{{count}} records',
relatedRecordOne: '{{count}} record',
noRelatedRecords: 'No related records found',
loading: 'Loading...',
copyToClipboard: 'Copy to clipboard',
copied: 'Copied!',
deleteConfirmation: 'Are you sure you want to delete this record?',
editRecord: 'Edit record',
viewAll: 'View All',
new: 'New',
emptyValue: '—',
},
chart: {
noData: 'No chart data available',
loading: 'Loading chart...',
Expand Down
35 changes: 35 additions & 0 deletions packages/i18n/src/locales/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,41 @@ const es = {
deleteCard: 'Eliminar tarjeta',
deleteColumn: 'Eliminar columna',
},
detail: {
back: 'Volver',
edit: 'Editar',
editInline: 'Editar en línea',
save: 'Guardar',
saveChanges: 'Guardar cambios',
editFieldsInline: 'Editar campos en línea',
share: 'Compartir',
duplicate: 'Duplicar',
export: 'Exportar',
viewHistory: 'Ver historial',
delete: 'Eliminar',
moreActions: 'Más acciones',
addToFavorites: 'Añadir a favoritos',
removeFromFavorites: 'Quitar de favoritos',
previousRecord: 'Registro anterior',
nextRecord: 'Siguiente registro',
recordOf: '{{current}} de {{total}}',
recordNotFound: 'Registro no encontrado',
recordNotFoundDescription: 'El registro que busca no existe o puede haber sido eliminado.',
goBack: 'Volver',
details: 'Detalles',
related: 'Relacionados',
relatedRecords: '{{count}} registros',
relatedRecordOne: '{{count}} registro',
noRelatedRecords: 'No se encontraron registros relacionados',
loading: 'Cargando...',
copyToClipboard: 'Copiar al portapapeles',
copied: '¡Copiado!',
deleteConfirmation: '¿Está seguro de que desea eliminar este registro?',
editRecord: 'Editar registro',
viewAll: 'Ver todo',
new: 'Nuevo',
emptyValue: '—',
},
chart: {
noData: 'No hay datos de gráfico disponibles',
loading: 'Cargando gráfico...',
Expand Down
35 changes: 35 additions & 0 deletions packages/i18n/src/locales/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,41 @@ const fr = {
deleteCard: 'Supprimer la carte',
deleteColumn: 'Supprimer la colonne',
},
detail: {
back: 'Retour',
edit: 'Modifier',
editInline: 'Modifier en ligne',
save: 'Enregistrer',
saveChanges: 'Enregistrer les modifications',
editFieldsInline: 'Modifier les champs en ligne',
share: 'Partager',
duplicate: 'Dupliquer',
export: 'Exporter',
viewHistory: "Voir l'historique",
delete: 'Supprimer',
moreActions: "Plus d'actions",
addToFavorites: 'Ajouter aux favoris',
removeFromFavorites: 'Retirer des favoris',
previousRecord: 'Enregistrement précédent',
nextRecord: 'Enregistrement suivant',
recordOf: '{{current}} sur {{total}}',
recordNotFound: 'Enregistrement introuvable',
recordNotFoundDescription: "L'enregistrement que vous recherchez n'existe pas ou a peut-être été supprimé.",
goBack: 'Retour',
details: 'Détails',
related: 'Associés',
relatedRecords: '{{count}} enregistrements',
relatedRecordOne: '{{count}} enregistrement',
noRelatedRecords: 'Aucun enregistrement associé trouvé',
loading: 'Chargement...',
copyToClipboard: 'Copier dans le presse-papiers',
copied: 'Copié !',
deleteConfirmation: 'Êtes-vous sûr de vouloir supprimer cet enregistrement ?',
editRecord: "Modifier l'enregistrement",
viewAll: 'Tout afficher',
new: 'Nouveau',
emptyValue: '—',
},
chart: {
noData: 'Aucune donnée de graphique disponible',
loading: 'Chargement du graphique...',
Expand Down
35 changes: 35 additions & 0 deletions packages/i18n/src/locales/ja.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,41 @@ const ja = {
deleteCard: 'カードを削除',
deleteColumn: 'カラムを削除',
},
detail: {
back: '戻る',
edit: '編集',
editInline: 'インライン編集',
save: '保存',
saveChanges: '変更を保存',
editFieldsInline: 'フィールドをインライン編集',
share: '共有',
duplicate: '複製',
export: 'エクスポート',
viewHistory: '履歴を表示',
delete: '削除',
moreActions: 'その他の操作',
addToFavorites: 'お気に入りに追加',
removeFromFavorites: 'お気に入りから削除',
previousRecord: '前のレコード',
nextRecord: '次のレコード',
recordOf: '{{current}} / {{total}}',
recordNotFound: 'レコードが見つかりません',
recordNotFoundDescription: 'お探しのレコードは存在しないか、削除された可能性があります。',
goBack: '戻る',
details: '詳細',
related: '関連',
relatedRecords: '{{count}} 件のレコード',
relatedRecordOne: '{{count}} 件のレコード',
noRelatedRecords: '関連レコードが見つかりません',
loading: '読み込み中...',
copyToClipboard: 'クリップボードにコピー',
copied: 'コピーしました!',
deleteConfirmation: 'このレコードを削除してもよろしいですか?',
editRecord: 'レコードを編集',
viewAll: 'すべて表示',
new: '新規',
emptyValue: '—',
},
chart: {
noData: 'チャートデータがありません',
loading: 'チャート読み込み中...',
Expand Down
35 changes: 35 additions & 0 deletions packages/i18n/src/locales/ko.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,41 @@ const ko = {
deleteCard: '카드 삭제',
deleteColumn: '열 삭제',
},
detail: {
back: '뒤로',
edit: '편집',
editInline: '인라인 편집',
save: '저장',
saveChanges: '변경사항 저장',
editFieldsInline: '필드 인라인 편집',
share: '공유',
duplicate: '복제',
export: '내보내기',
viewHistory: '기록 보기',
delete: '삭제',
moreActions: '더 많은 작업',
addToFavorites: '즐겨찾기에 추가',
removeFromFavorites: '즐겨찾기에서 제거',
previousRecord: '이전 레코드',
nextRecord: '다음 레코드',
recordOf: '{{current}} / {{total}}',
recordNotFound: '레코드를 찾을 수 없음',
recordNotFoundDescription: '찾으시는 레코드가 존재하지 않거나 삭제되었을 수 있습니다.',
goBack: '뒤로',
details: '상세정보',
related: '관련',
relatedRecords: '{{count}}개 레코드',
relatedRecordOne: '{{count}}개 레코드',
noRelatedRecords: '관련 레코드를 찾을 수 없습니다',
loading: '로딩 중...',
copyToClipboard: '클립보드에 복사',
copied: '복사됨!',
deleteConfirmation: '이 레코드를 삭제하시겠습니까?',
editRecord: '레코드 편집',
viewAll: '모두 보기',
new: '새로 만들기',
emptyValue: '—',
},
chart: {
noData: '차트 데이터가 없습니다',
loading: '차트 로딩 중...',
Expand Down
35 changes: 35 additions & 0 deletions packages/i18n/src/locales/pt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,41 @@ const pt = {
deleteCard: 'Excluir cartão',
deleteColumn: 'Excluir coluna',
},
detail: {
back: 'Voltar',
edit: 'Editar',
editInline: 'Editar inline',
save: 'Salvar',
saveChanges: 'Salvar alterações',
editFieldsInline: 'Editar campos inline',
share: 'Compartilhar',
duplicate: 'Duplicar',
export: 'Exportar',
viewHistory: 'Ver histórico',
delete: 'Excluir',
moreActions: 'Mais ações',
addToFavorites: 'Adicionar aos favoritos',
removeFromFavorites: 'Remover dos favoritos',
previousRecord: 'Registro anterior',
nextRecord: 'Próximo registro',
recordOf: '{{current}} de {{total}}',
recordNotFound: 'Registro não encontrado',
recordNotFoundDescription: 'O registro que você está procurando não existe ou pode ter sido excluído.',
goBack: 'Voltar',
details: 'Detalhes',
related: 'Relacionados',
relatedRecords: '{{count}} registros',
relatedRecordOne: '{{count}} registro',
noRelatedRecords: 'Nenhum registro relacionado encontrado',
loading: 'Carregando...',
copyToClipboard: 'Copiar para área de transferência',
copied: 'Copiado!',
deleteConfirmation: 'Tem certeza de que deseja excluir este registro?',
editRecord: 'Editar registro',
viewAll: 'Ver tudo',
new: 'Novo',
emptyValue: '—',
},
chart: {
noData: 'Nenhum dado de gráfico disponível',
loading: 'Carregando gráfico...',
Expand Down
Loading