diff --git a/packages/sanity/src/core/i18n/bundles/studio.ts b/packages/sanity/src/core/i18n/bundles/studio.ts
index a82b60410e4..cc7faa22c5a 100644
--- a/packages/sanity/src/core/i18n/bundles/studio.ts
+++ b/packages/sanity/src/core/i18n/bundles/studio.ts
@@ -68,6 +68,9 @@ export const studioLocaleStrings = {
/** Label for loading history */
'timeline.loading-history': 'Loading history',
+ /** The aria-label for the list of revisions in the timeline */
+ 'timeline.list.aria-label': 'Document revisions',
+
/**
* Label for determining since which version the changes for timeline menu dropdown are showing.
* Receives the time label as a parameter.
diff --git a/packages/sanity/src/desk/i18n/resources.ts b/packages/sanity/src/desk/i18n/resources.ts
index a30801bd2aa..30ef9eb8a41 100644
--- a/packages/sanity/src/desk/i18n/resources.ts
+++ b/packages/sanity/src/desk/i18n/resources.ts
@@ -166,6 +166,160 @@ const deskLocaleStrings = {
/** --- "PRODUCTION PREVIEW", eg link to content --- */
'production-preview.menu-item.title': 'Open preview',
+ /** -- DESK PANES -- */
+ /** The tool tip for the split pane button on the document panel header */
+ 'buttons.split-pane-button.tooltip': 'Split pane right',
+
+ /** The aria-label for the split pane button on the document panel header */
+ 'buttons.split-pane-button.aria-label': 'Split pane right',
+
+ /** The title for the close button on the split pane on the document panel header */
+ 'buttons.split-pane-close-button.title': 'Close split pane',
+
+ /** The title for the close group button on the split pane on the document panel header */
+ 'buttons.split-pane-close-group-button.title': 'Close pane group',
+
+ /** The text content for the deleted document banner */
+ 'banners.deleted-document-banner.text': 'This document has been deleted.',
+
+ /** The text for the restore button on the deleted document banner */
+ 'banners.deleted-document-banner.restore-button.text': 'Restore most recent version',
+
+ /** The text for the reference change banner if the reason is that the reference has been changed */
+ 'banners.reference-changed-banner.reason-changed.text':
+ 'This reference has changed since you opened it.',
+
+ /** The text for the reload button */
+ 'banners.reference-changed-banner.reason-changed.reload-button.text': 'Reload reference',
+
+ /** The text for the reference change banner if the reason is that the reference has been deleted */
+ 'banners.reference-changed-banner.reason-removed.text':
+ 'This reference has been removed since you opened it.',
+
+ /** The text for the close button */
+ 'banners.reference-changed-banner.reason-removed.close-button.text': 'Close reference',
+
+ /** The text for the permission check banner if there is only one role */
+ 'banners.permission-check-banner.singular-role.text':
+ 'Your role {{roles}} does not have permissions to {{requiredPermission}} this document.',
+
+ /** The text for the permission check banner if there is are multiple roles */
+ 'banners.permission-check-banner.plural-roles.text':
+ 'Your roles {{roles}} do not have permissions to {{requiredPermission}} this document.',
+
+ /** The text for when a form is hidden */
+ 'document-view.form-view.form-hidden': 'This form is hidden',
+
+ /** The text for when the form view is loading a document */
+ 'document-view.form-view.loading': 'Loading document',
+
+ /** The title of the sync lock toast on the form view */
+ 'document-view.form-view.sync-lock-toast.title': 'Syncing document…',
+
+ /** The description of the sync lock toast on the form view */
+ 'document-view.form-view.sync-lock-toast.description':
+ 'Please hold tight while the document is synced. This usually happens right after the document has been published, and it should not take more than a few seconds',
+
+ /** The title of the reconnecting toast */
+ 'panes.document-pane-provider.reconnecting.title': 'Connection lost. Reconnecting…',
+
+ /** The loading message for the document not found pane */
+ 'panes.document-pane.document-not-found.loading': 'Loading document…',
+
+ /** The title of the document not found pane if the schema is known */
+ 'panes.document-pane.document-not-found.title': 'The document was not found',
+
+ /** The text of the document not found pane if the schema is known */
+ 'panes.document-pane.document-not-found.text':
+ 'The document type is not defined, and a document with the {{id}} identifier could not be found.',
+
+ /** The title of the document not found pane if the schema is not found or unknown */
+ 'panes.document-pane.document-unknown-type.title':
+ 'Unknown document type: {{documentType}}',
+
+ /** The text of the document not found pane if the schema is not found */
+ 'panes.document-pane.document-unknown-type.text':
+ 'This document has the schema type {{documentType}}, which is not defined as a type in the local content studio schema.',
+
+ /** The title of the document not found pane if the schema is unknown */
+ 'panes.document-pane.document-unknown-type.without-schema.text':
+ 'This document does not exist, and no schema type was specified for it.',
+
+ /** The text of the document list pane if more than a maximum number of documents are returned */
+ 'panes.document-list-pane.max-items.text': 'Displaying a maximum of {{limit}} documents',
+
+ /** The text of the document list pane if no documents are found */
+ 'panes.document-list-pane.no-documents.text': 'No results found',
+
+ /** The text of the document list pane if no documents are found matching specified criteria */
+ 'panes.document-list-pane.no-matching-documents.text': 'No matching documents',
+
+ /** The text of the document list pane if no documents are found for a specified type */
+ 'panes.document-list-pane.no-documents-of-type.text': 'No documents of this type',
+
+ /** The error title on the document list pane */
+ 'panes.document-list-pane.error.title': 'Could not fetch list items',
+
+ /** The error text on the document list pane */
+ 'panes.document-list-pane.error.text': 'Error: {{error}}',
+
+ /** The text for the retry button on the document list pane */
+ 'panes.document-list-pane.error.retry-button.text': 'Retry',
+
+ /** The summary title when displaying an error for a document operation result */
+ 'panes.document-operation-results.error.summary.title': 'Details',
+
+ /** The text when a delete operation failed */
+ 'panes.document-operation-results.operation-error_delete':
+ 'An error occurred while attempting to delete this document. This usually means that there are other documents that refers to it.',
+
+ /** The text when an unpublish operation failed */
+ 'panes.document-operation-results.operation-error_unpublish':
+ 'An error occurred while attempting to unpublish this document. This usually means that there are other documents that refers to it.',
+
+ /** The text when a generic operation failed */
+ 'panes.document-operation-results.operation-error': 'An error occurred during {{context}}',
+
+ /** The text when a publish operation succeded */
+ 'panes.document-operation-results.operation-success_publish': 'The document was published',
+
+ /** The text when an unpublish operation succeded */
+ 'panes.document-operation-results.operation-success_unpublish':
+ 'The document was unpublished. A draft has been created from the latest published version.',
+
+ /** The text when a discard changes operation succeded */
+ 'panes.document-operation-results.operation-success_discardChanges':
+ 'All changes since last publish has now been discarded. The discarded draft can still be recovered from history',
+
+ /** The text when a delete operation succeded */
+ 'panes.document-operation-results.operation-success_delete':
+ 'The document was successfully deleted',
+
+ /** The text when a generic operation succeded */
+ 'panes.document-operation-results.operation-success':
+ 'Successfully performed {{context}} on document',
+
+ /** The text used in the document header title if creating a new item */
+ 'panes.document-header-title.new.text': 'New {{schemaType}}',
+
+ /** The text used in the document header title if there is an error */
+ 'panes.document-header-title.error.text': 'Error: {{error}}',
+
+ /** The text used in the document header title if no other title can be determined */
+ 'panes.document-header-title.untitled.text': 'Untitled',
+
+ /** The aria-label for the search input on the document list pane */
+ 'panes.document-list-pane.search-input.aria-label': 'Search list',
+
+ /** The search input for the search input on the document list pane */
+ 'panes.document-list-pane.search-input.placeholder': 'Search list',
+
+ /** The action menu button aria-label */
+ 'buttons.action-menu-button.aria-label': 'Open document actions',
+
+ /** the placeholder text for the search input on the inspect dialog */
+ 'inputs.inspect-dialog.search.placeholder': 'Search',
+
/** -- UNKNOWN PANE TYPE */
/** The text to display when type is missing */
@@ -175,6 +329,9 @@ const deskLocaleStrings = {
/** The text to display when type is unknown */
'panes.unknown-pane-type.unknown-type.text':
'Structure item of type {{type}} is not a known entity.',
+
+ /** The title of the unknown pane */
+ 'panes.unknown-pane-type.title': 'Unknown pane type',
}
/**
diff --git a/packages/sanity/src/desk/panes/document/DocumentOperationResults.tsx b/packages/sanity/src/desk/panes/document/DocumentOperationResults.tsx
index 089c173a5d9..cfb9b3fabd8 100644
--- a/packages/sanity/src/desk/panes/document/DocumentOperationResults.tsx
+++ b/packages/sanity/src/desk/panes/document/DocumentOperationResults.tsx
@@ -1,36 +1,9 @@
import {useToast} from '@sanity/ui'
import React, {memo, useEffect, useRef} from 'react'
import {useDocumentPane} from './useDocumentPane'
-import {useDocumentOperationEvent} from 'sanity'
+import {useDocumentOperationEvent, useTranslation} from 'sanity'
import {usePaneRouter} from '../../components'
-
-function getOpErrorTitle(op: string): string {
- if (op === 'delete') {
- return `An error occurred while attempting to delete this document.
- This usually means that there are other documents that refers to it.`
- }
- if (op === 'unpublish') {
- return `An error occurred while attempting to unpublish this document.
- This usually means that there are other documents that refers to it.`
- }
- return `An error occurred during ${op}`
-}
-
-function getOpSuccessTitle(op: string): string {
- if (op === 'publish') {
- return `The document was published`
- }
- if (op === 'unpublish') {
- return `The document was unpublished. A draft has been created from the latest published version.`
- }
- if (op === 'discardChanges') {
- return `All changes since last publish has now been discarded. The discarded draft can still be recovered from history`
- }
- if (op === 'delete') {
- return `The document was successfully deleted`
- }
- return `Successfully performed ${op} on document`
-}
+import {deskLocaleNamespace} from '../../i18n'
const IGNORE_OPS = ['patch', 'commit']
@@ -40,6 +13,7 @@ export const DocumentOperationResults = memo(function DocumentOperationResults()
const event: any = useDocumentOperationEvent(documentId, documentType)
const prevEvent = useRef(event)
const paneRouter = usePaneRouter()
+ const {t} = useTranslation(deskLocaleNamespace)
useEffect(() => {
if (!event || event === prevEvent.current) return
@@ -51,10 +25,10 @@ export const DocumentOperationResults = memo(function DocumentOperationResults()
closable: true,
duration: 30000, // 30s
status: 'error',
- title: getOpErrorTitle(event.op),
+ title: t('panes.document-operation-results.operation-error', {context: event.op}),
description: (
- Details
+ {t('panes.document-operation-results.error.summary.title')}
{event.error.message}
),
@@ -65,7 +39,7 @@ export const DocumentOperationResults = memo(function DocumentOperationResults()
pushToast({
closable: true,
status: 'success',
- title: getOpSuccessTitle(event.op),
+ title: t('panes.document-operation-results.operation-success', {context: event.op}),
})
}
@@ -81,7 +55,7 @@ export const DocumentOperationResults = memo(function DocumentOperationResults()
// eslint-disable-next-line consistent-return
return () => clearTimeout(cleanupId)
- }, [event, paneRouter, pushToast])
+ }, [event, paneRouter, pushToast, t])
return null
})
diff --git a/packages/sanity/src/desk/panes/document/DocumentPane.tsx b/packages/sanity/src/desk/panes/document/DocumentPane.tsx
index 803efe987e4..23e5e64aff0 100644
--- a/packages/sanity/src/desk/panes/document/DocumentPane.tsx
+++ b/packages/sanity/src/desk/panes/document/DocumentPane.tsx
@@ -31,15 +31,18 @@ import {
DOCUMENT_PANEL_INITIAL_MIN_WIDTH,
DOCUMENT_PANEL_MIN_WIDTH,
} from './constants'
+import {deskLocaleNamespace} from '../../i18n'
import {
ChangeConnectorRoot,
ReferenceInputOptionsProvider,
SourceProvider,
isDev,
+ Translate,
useDocumentType,
useSource,
useTemplatePermissions,
useTemplates,
+ useTranslation,
useZIndex,
} from 'sanity'
import {CommentsEnabledProvider} from '../../comments'
@@ -122,8 +125,17 @@ function DocumentPaneInner(props: DocumentPaneProviderProps) {
: {path: [], state: 'none'}
}, [parentRefPath, groupIndex, routerPanesStateLength])
+ const {t} = useTranslation(deskLocaleNamespace)
+
if (options.type === '*' && !isLoaded) {
- return
+ return (
+
+ )
}
if (!documentType) {
@@ -132,12 +144,16 @@ function DocumentPaneInner(props: DocumentPaneProviderProps) {
flex={2.5}
minWidth={320}
paneKey={paneKey}
- title={<>The document was not found>}
+ title={t('panes.document-pane.document-not-found.title')}
>
- The document type is not defined, and a document with the {options.id}{' '}
- identifier could not be found.
+ {children}}}
+ values={{id: options.id}}
+ />
@@ -246,6 +262,7 @@ function InnerDocumentPane() {
DOCUMENT_PANEL_INITIAL_MIN_WIDTH + (inspector ? DOCUMENT_INSPECTOR_MIN_WIDTH : 0)
const minWidth = DOCUMENT_PANEL_MIN_WIDTH + (inspector ? DOCUMENT_INSPECTOR_MIN_WIDTH : 0)
+ const {t} = useTranslation(deskLocaleNamespace)
if (!schemaType) {
return (
@@ -255,27 +272,33 @@ function InnerDocumentPane() {
minWidth={minWidth}
paneKey={paneKey}
title={
- <>
- Unknown document type: {documentType}
- >
+ {children}}}
+ values={{documentType}}
+ />
}
tone="caution"
>
{documentType && (
- This document has the schema type {documentType}, which is not defined as
- a type in the local content studio schema.
+ {children}}}
+ values={{documentType}}
+ />
)}
{!documentType && (
-
- This document does not exist, and no schema type was specified for it.
-
+ {t('panes.document-pane.document-unknown-type.without-schema.text')}
)}
{isDev && value && (
+ /* eslint-disable i18next/no-literal-string */
<>
Here is the JSON representation of the document:
@@ -284,6 +307,7 @@ function InnerDocumentPane() {
>
+ /* eslint-enable i18next/no-literal-string */
)}
diff --git a/packages/sanity/src/desk/panes/document/DocumentPaneProvider.tsx b/packages/sanity/src/desk/panes/document/DocumentPaneProvider.tsx
index c5032decf87..4c86f6ff3c0 100644
--- a/packages/sanity/src/desk/panes/document/DocumentPaneProvider.tsx
+++ b/packages/sanity/src/desk/panes/document/DocumentPaneProvider.tsx
@@ -662,10 +662,10 @@ export const DocumentPaneProvider = memo((props: DocumentPaneProviderProps) => {
pushToast({
id: 'sanity/desk/reconnecting',
status: 'warning',
- title: <>Connection lost. Reconnecting…>,
+ title: t('panes.document-pane-provider.reconnecting.title'),
})
}
- }, [connectionState, pushToast])
+ }, [connectionState, pushToast, t])
const disableBlurRef = useRef(false)
diff --git a/packages/sanity/src/desk/panes/document/documentPanel/DeletedDocumentBanner.tsx b/packages/sanity/src/desk/panes/document/documentPanel/DeletedDocumentBanner.tsx
index f4bca949be4..e932b94f7df 100644
--- a/packages/sanity/src/desk/panes/document/documentPanel/DeletedDocumentBanner.tsx
+++ b/packages/sanity/src/desk/panes/document/documentPanel/DeletedDocumentBanner.tsx
@@ -3,8 +3,9 @@ import {Button, Card, Container, Flex, Text} from '@sanity/ui'
import {ReadOnlyIcon} from '@sanity/icons'
import styled from 'styled-components'
import {useDocumentPane} from '../useDocumentPane'
-import {useDocumentOperation} from 'sanity'
+import {useDocumentOperation, useTranslation} from 'sanity'
import {useRouter} from 'sanity/router'
+import {deskLocaleNamespace} from '../../../i18n'
const Root = styled(Card)`
position: relative;
@@ -25,6 +26,7 @@ export function DeletedDocumentBanner({revisionId}: DeletedDocumentBannerProps)
navigateIntent('edit', {id: documentId, type: documentType})
}
}, [documentId, documentType, navigateIntent, restore, revisionId])
+ const {t} = useTranslation(deskLocaleNamespace)
return (
@@ -35,7 +37,7 @@ export function DeletedDocumentBanner({revisionId}: DeletedDocumentBannerProps)
- This document has been deleted.
+ {t('banners.deleted-document-banner.text')}
{revisionId && (
)}
diff --git a/packages/sanity/src/desk/panes/document/documentPanel/PermissionCheckBanner.tsx b/packages/sanity/src/desk/panes/document/documentPanel/PermissionCheckBanner.tsx
index 78a18acc273..82c8c0cc173 100644
--- a/packages/sanity/src/desk/panes/document/documentPanel/PermissionCheckBanner.tsx
+++ b/packages/sanity/src/desk/panes/document/documentPanel/PermissionCheckBanner.tsx
@@ -2,7 +2,8 @@ import React from 'react'
import {Box, Card, Container, Flex, Text} from '@sanity/ui'
import {ReadOnlyIcon} from '@sanity/icons'
import styled from 'styled-components'
-import {useCurrentUser} from 'sanity'
+import {deskLocaleNamespace} from '../../../i18n'
+import {useCurrentUser, useTranslation} from 'sanity'
const Root = styled(Card)`
position: relative;
@@ -22,6 +23,7 @@ export function PermissionCheckBanner({granted, requiredPermission}: PermissionC
currentUser?.roles?.map((r) => {r.title}) || [],
', ',
)
+ const {t} = useTranslation(deskLocaleNamespace)
if (granted) return null
@@ -35,8 +37,15 @@ export function PermissionCheckBanner({granted, requiredPermission}: PermissionC
- Your role{plural && 's'} {roles} {plural ? 'do' : 'does'} not have permissions to{' '}
- {requiredPermission} this document.
+ {plural
+ ? t('banners.permission-check-banner.plural-roles.text', {
+ roles,
+ requiredPermission,
+ })
+ : t('banners.permission-check-banner.singular-role.text', {
+ roles,
+ requiredPermission,
+ })}
diff --git a/packages/sanity/src/desk/panes/document/documentPanel/ReferenceChangedBanner.tsx b/packages/sanity/src/desk/panes/document/documentPanel/ReferenceChangedBanner.tsx
index 7e4f008f0c4..849c162ba2f 100644
--- a/packages/sanity/src/desk/panes/document/documentPanel/ReferenceChangedBanner.tsx
+++ b/packages/sanity/src/desk/panes/document/documentPanel/ReferenceChangedBanner.tsx
@@ -9,7 +9,8 @@ import {concat, Observable, of} from 'rxjs'
import {useMemoObservable} from 'react-rx'
import {RouterPaneGroup} from '../../../types'
import {usePaneRouter} from '../../../components'
-import {DocumentAvailability, useDocumentPreviewStore, getPublishedId} from 'sanity'
+import {deskLocaleNamespace} from '../../../i18n'
+import {DocumentAvailability, useDocumentPreviewStore, getPublishedId, useTranslation} from 'sanity'
const Root = styled(Card)`
position: relative;
@@ -44,6 +45,7 @@ export const ReferenceChangedBanner = memo(() => {
const parentRefPath = useMemo(() => {
return (params?.parentRefPath && pathFromString(params.parentRefPath)) || null
}, [params?.parentRefPath])
+ const {t} = useTranslation(deskLocaleNamespace)
/**
* Loads information regarding the reference field of the parent pane. This
@@ -148,8 +150,11 @@ export const ReferenceChangedBanner = memo(() => {
{referenceInfo.result?.refValue ? (
<>
-
- This reference has changed since you opened it.
+
+ {t('banners.reference-changed-banner.reason-changed.text')}
@@ -160,15 +165,18 @@ export const ReferenceChangedBanner = memo(() => {
mode="ghost"
padding={2}
space={2}
- text="Reload reference"
+ text={t('banners.reference-changed-banner.reason-changed.reload-button.text')}
/>
>
) : (
<>
-
- This reference has been removed since you opened it.
+
+ {t('banners.reference-changed-banner.reason-removed.text')}
@@ -179,7 +187,7 @@ export const ReferenceChangedBanner = memo(() => {
mode="ghost"
padding={2}
space={2}
- text="Close reference"
+ text={t('banners.reference-changed-banner.reason-removed.close-button.text')}
/>
>
diff --git a/packages/sanity/src/desk/panes/document/documentPanel/documentViews/FormView.tsx b/packages/sanity/src/desk/panes/document/documentPanel/documentViews/FormView.tsx
index 338398c7171..70c951e53d7 100644
--- a/packages/sanity/src/desk/panes/document/documentPanel/documentViews/FormView.tsx
+++ b/packages/sanity/src/desk/panes/document/documentPanel/documentViews/FormView.tsx
@@ -6,6 +6,7 @@ import {tap} from 'rxjs/operators'
import {useDocumentPane} from '../../useDocumentPane'
import {Delay} from '../../../../components/Delay'
import {useConditionalToast} from './useConditionalToast'
+import {deskLocaleNamespace} from '../../../../i18n'
import {
FormDocumentValue,
DocumentMutationEvent,
@@ -17,6 +18,7 @@ import {
fromMutationPatches,
useDocumentPresence,
useDocumentStore,
+ useTranslation,
} from 'sanity'
interface FormViewProps {
@@ -58,13 +60,14 @@ export const FormView = forwardRef(function FormV
const patchChannel = useMemo(() => createPatchChannel(), [])
const isLocked = editState?.transactionSyncLock?.enabled
+ const {t} = useTranslation(deskLocaleNamespace)
useConditionalToast({
id: `sync-lock-${documentId}`,
status: 'warning',
enabled: isLocked,
- title: `Syncing document…`,
- description: `Please hold tight while the document is synced. This usually happens right after the document has been published, and it shouldn't take more than a few seconds`,
+ title: t('document-view.form-view.sync-lock-toast.title'),
+ description: t('document-view.form-view.sync-lock-toast.description'),
})
useEffect(() => {
@@ -153,7 +156,7 @@ export const FormView = forwardRef(function FormV
{ready ? (
formState === null ? (
- This form is hidden
+ {t('document-view.form-view.form-hidden')}
) : (
(function FormV
- Loading document
+ {t('document-view.form-view.loading')}
diff --git a/packages/sanity/src/desk/panes/document/documentPanel/header/DocumentHeaderTitle.test.tsx b/packages/sanity/src/desk/panes/document/documentPanel/header/DocumentHeaderTitle.test.tsx
index be001243b64..014d7cba1ee 100644
--- a/packages/sanity/src/desk/panes/document/documentPanel/header/DocumentHeaderTitle.test.tsx
+++ b/packages/sanity/src/desk/panes/document/documentPanel/header/DocumentHeaderTitle.test.tsx
@@ -1,12 +1,34 @@
import React from 'react'
-import {render} from '@testing-library/react'
+import {render, waitFor} from '@testing-library/react'
import {useDocumentPane} from '../../useDocumentPane'
import {DocumentPaneContextValue} from '../../DocumentPaneContext'
+import {createTestProvider} from '../../../../../../test/testUtils/TestProvider'
+import {createMockSanityClient} from '../../../../../../test/mocks/mockSanityClient'
+import {deskUsEnglishLocaleBundle} from '../../../../i18n'
import {DocumentHeaderTitle} from './DocumentHeaderTitle'
-import {unstable_useValuePreview as useValuePreview} from 'sanity'
+import {SanityClient, defineConfig, unstable_useValuePreview as useValuePreview} from 'sanity'
+
+function createWrapperComponent(client: SanityClient) {
+ const config = defineConfig({
+ projectId: 'test',
+ dataset: 'test',
+ })
+
+ return createTestProvider({
+ client,
+ config,
+ resources: [deskUsEnglishLocaleBundle],
+ })
+}
jest.mock('../../useDocumentPane')
-jest.mock('sanity')
+jest.mock('sanity', () => {
+ const actual = jest.requireActual('sanity')
+ return {
+ ...actual,
+ unstable_useValuePreview: jest.fn(),
+ }
+})
describe('DocumentHeaderTitle', () => {
const mockUseDocumentPane = useDocumentPane as jest.MockedFunction
@@ -31,80 +53,113 @@ describe('DocumentHeaderTitle', () => {
jest.resetAllMocks()
})
- it('should render without crashing', () => {
- const {getByText} = render()
- expect(getByText('Untitled')).toBeInTheDocument()
+ it('should render without crashing', async () => {
+ const client = createMockSanityClient()
+ const wrapper = await createWrapperComponent(client as any)
+
+ const {getByText} = render(, {wrapper})
+ await waitFor(() => expect(getByText('Untitled')).toBeInTheDocument())
})
- it('should return an empty fragment when connectionState is not "connected"', () => {
+ it('should return an empty fragment when connectionState is not "connected"', async () => {
mockUseDocumentPane.mockReturnValue({
...defaultProps,
connectionState: 'connecting',
} as unknown as DocumentPaneContextValue)
+
const {container} = render()
- expect(container.firstChild).toBeNull()
+ await waitFor(() => expect(container.firstChild).toBeNull())
})
- it('should return the title if it is provided', () => {
+ it('should return the title if it is provided', async () => {
mockUseDocumentPane.mockReturnValue({
...defaultProps,
title: 'Test Title',
} as unknown as DocumentPaneContextValue)
- const {getByText} = render()
- expect(getByText('Test Title')).toBeInTheDocument()
+
+ const client = createMockSanityClient()
+ const wrapper = await createWrapperComponent(client as any)
+
+ const {getByText} = render(, {wrapper})
+ await waitFor(() => expect(getByText('Test Title')).toBeInTheDocument())
})
- it('should return "New {schemaType?.title || schemaType?.name}" if documentValue is not provided', () => {
+ it('should return "New {schemaType?.title || schemaType?.name}" if documentValue is not provided', async () => {
mockUseDocumentPane.mockReturnValue({
...defaultProps,
value: null,
} as unknown as DocumentPaneContextValue)
- const {getByText} = render()
- expect(getByText('New Test Schema')).toBeInTheDocument()
+
+ const client = createMockSanityClient()
+ const wrapper = await createWrapperComponent(client as any)
+
+ const {getByText} = render(, {wrapper})
+ await waitFor(() => expect(getByText('New Test Schema')).toBeInTheDocument())
})
- it('should return the value.title if value is provided and no error occurred', () => {
+ it('should return the value.title if value is provided and no error occurred', async () => {
mockUseValuePreview.mockReturnValue({
...defaultValue,
error: undefined,
value: {title: 'Test Preview Value'},
})
- const {getByText} = render()
- expect(getByText('Test Preview Value')).toBeInTheDocument()
+
+ const client = createMockSanityClient()
+ const wrapper = await createWrapperComponent(client as any)
+
+ const {getByText} = render(, {wrapper})
+ await waitFor(() => expect(getByText('Test Preview Value')).toBeInTheDocument())
})
- it('should return "Untitled" if value is not provided and no error occurred', () => {
+ it('should return "Untitled" if value is not provided and no error occurred', async () => {
mockUseValuePreview.mockReturnValue({...defaultValue, error: undefined, value: undefined})
- const {getByText} = render()
- expect(getByText('Untitled')).toBeInTheDocument()
+
+ const client = createMockSanityClient()
+ const wrapper = await createWrapperComponent(client as any)
+
+ const {getByText} = render(, {wrapper})
+ await waitFor(() => expect(getByText('Untitled')).toBeInTheDocument())
})
- it('should return "Error: {error.message}" if an error occurred while getting the preview value', () => {
+ it('should return "Error: {error.message}" if an error occurred while getting the preview value', async () => {
mockUseValuePreview.mockReturnValue({
...defaultValue,
error: new Error('Test Error'),
value: undefined,
})
- const {getByText} = render()
- expect(getByText('Error: Test Error')).toBeInTheDocument()
+
+ const client = createMockSanityClient()
+ const wrapper = await createWrapperComponent(client as any)
+
+ const {getByText} = render(, {wrapper})
+ await waitFor(() => expect(getByText('Error: Test Error')).toBeInTheDocument())
})
- it('should call useValuePreview hook with the correct arguments', () => {
- render()
- expect(mockUseValuePreview).toHaveBeenCalledWith({
- enabled: true,
- schemaType: defaultProps.schemaType,
- value: defaultProps.value,
- })
+ it('should call useValuePreview hook with the correct arguments', async () => {
+ const client = createMockSanityClient()
+ const wrapper = await createWrapperComponent(client as any)
+
+ render(, {wrapper})
+ await waitFor(() =>
+ expect(mockUseValuePreview).toHaveBeenCalledWith({
+ enabled: true,
+ schemaType: defaultProps.schemaType,
+ value: defaultProps.value,
+ }),
+ )
})
- it('should display the value returned by useValuePreview hook correctly when no error occurs', () => {
+ it('should display the value returned by useValuePreview hook correctly when no error occurs', async () => {
mockUseValuePreview.mockReturnValue({
...defaultValue,
error: undefined,
value: {title: 'Test Preview Value'},
})
- const {getByText} = render()
- expect(getByText('Test Preview Value')).toBeInTheDocument()
+
+ const client = createMockSanityClient()
+ const wrapper = await createWrapperComponent(client as any)
+
+ const {getByText} = render(, {wrapper})
+ await waitFor(() => expect(getByText('Test Preview Value')).toBeInTheDocument())
})
})
diff --git a/packages/sanity/src/desk/panes/document/documentPanel/header/DocumentHeaderTitle.tsx b/packages/sanity/src/desk/panes/document/documentPanel/header/DocumentHeaderTitle.tsx
index cf7455d5cb3..66ff52ed146 100644
--- a/packages/sanity/src/desk/panes/document/documentPanel/header/DocumentHeaderTitle.tsx
+++ b/packages/sanity/src/desk/panes/document/documentPanel/header/DocumentHeaderTitle.tsx
@@ -1,6 +1,7 @@
import React, {ReactElement} from 'react'
import {useDocumentPane} from '../../useDocumentPane'
-import {unstable_useValuePreview as useValuePreview} from 'sanity'
+import {deskLocaleNamespace} from '../../../../i18n'
+import {unstable_useValuePreview as useValuePreview, useTranslation} from 'sanity'
export function DocumentHeaderTitle(): ReactElement {
const {connectionState, schemaType, title, value: documentValue} = useDocumentPane()
@@ -11,6 +12,7 @@ export function DocumentHeaderTitle(): ReactElement {
schemaType,
value: documentValue,
})
+ const {t} = useTranslation(deskLocaleNamespace)
if (connectionState !== 'connected') {
return <>>
@@ -21,12 +23,26 @@ export function DocumentHeaderTitle(): ReactElement {
}
if (!documentValue) {
- return <>New {schemaType?.title || schemaType?.name}>
+ return (
+ <>
+ {t('panes.document-header-title.new.text', {
+ schemaType: schemaType?.title || schemaType?.name,
+ })}
+ >
+ )
}
if (error) {
- return <>Error: {error.message}>
+ return <>{t('panes.document-header-title.error.text', {error: error.message})}>
}
- return <>{value?.title || Untitled}>
+ return (
+ <>
+ {value?.title || (
+
+ {t('panes.document-header-title.untitled.text')}
+
+ )}
+ >
+ )
}
diff --git a/packages/sanity/src/desk/panes/document/documentPanel/header/DocumentPanelHeader.tsx b/packages/sanity/src/desk/panes/document/documentPanel/header/DocumentPanelHeader.tsx
index b8a8efa4169..11e6e5cb35d 100644
--- a/packages/sanity/src/desk/panes/document/documentPanel/header/DocumentPanelHeader.tsx
+++ b/packages/sanity/src/desk/panes/document/documentPanel/header/DocumentPanelHeader.tsx
@@ -14,7 +14,8 @@ import {isMenuNodeButton, isNotMenuNodeButton, resolveMenuNodes} from '../../../
import {useDeskTool} from '../../../../useDeskTool'
import {DocumentHeaderTabs} from './DocumentHeaderTabs'
import {DocumentHeaderTitle} from './DocumentHeaderTitle'
-import {useFieldActions, useTimelineSelector} from 'sanity'
+import {deskLocaleNamespace} from '../../../../i18n'
+import {useFieldActions, useTimelineSelector, useTranslation} from 'sanity'
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface DocumentPanelHeaderProps {}
@@ -74,6 +75,7 @@ export const DocumentPanelHeader = memo(
// and if the back button is not showing (the back button and the close
// button) do the same thing and shouldn't be shown at the same time)
const showPaneGroupCloseButton = !showSplitPaneCloseButton && !features.backButton
+ const {t} = useTranslation(deskLocaleNamespace)
return (
- Split pane right
+ {t('buttons.split-pane-button.tooltip')}
}
padding={2}
@@ -121,7 +123,7 @@ export const DocumentPanelHeader = memo(
portal
>
)}
@@ -145,7 +147,7 @@ export const DocumentPanelHeader = memo(
icon={CloseIcon}
key="close-view-button"
mode="bleed"
- title="Close pane group"
+ title={t('buttons.split-pane-close-group-button.title')}
as={BackLink}
/>
)}
diff --git a/packages/sanity/src/desk/panes/document/inspectDialog/Search.tsx b/packages/sanity/src/desk/panes/document/inspectDialog/Search.tsx
index 130407feed3..6493653de29 100644
--- a/packages/sanity/src/desk/panes/document/inspectDialog/Search.tsx
+++ b/packages/sanity/src/desk/panes/document/inspectDialog/Search.tsx
@@ -1,6 +1,8 @@
import {SearchIcon} from '@sanity/icons'
import {TextInput} from '@sanity/ui'
import React, {useCallback} from 'react'
+import {deskLocaleNamespace} from '../../../i18n'
+import {useTranslation} from 'sanity'
export function Search(props: {onChange: (q: string) => void; query: string}) {
const {onChange, query} = props
@@ -9,12 +11,13 @@ export function Search(props: {onChange: (q: string) => void; query: string}) {
(event: React.ChangeEvent) => onChange(event.target.value),
[onChange],
)
+ const {t} = useTranslation(deskLocaleNamespace)
return (
diff --git a/packages/sanity/src/desk/panes/document/inspectors/validation/ValidationInspector.tsx b/packages/sanity/src/desk/panes/document/inspectors/validation/ValidationInspector.tsx
index f1849a6500a..9f9d5a14280 100644
--- a/packages/sanity/src/desk/panes/document/inspectors/validation/ValidationInspector.tsx
+++ b/packages/sanity/src/desk/panes/document/inspectors/validation/ValidationInspector.tsx
@@ -84,7 +84,7 @@ function ValidationCard(props: {
{errorInfo && (
- ERROR: {errorInfo.error.message}
+ {errorInfo.error.message}
)}
diff --git a/packages/sanity/src/desk/panes/document/statusBar/ActionMenuButton.tsx b/packages/sanity/src/desk/panes/document/statusBar/ActionMenuButton.tsx
index 886c4eb4270..43237330111 100644
--- a/packages/sanity/src/desk/panes/document/statusBar/ActionMenuButton.tsx
+++ b/packages/sanity/src/desk/panes/document/statusBar/ActionMenuButton.tsx
@@ -14,14 +14,15 @@ import React, {
createElement,
isValidElement,
useCallback,
+ useId,
+ useMemo,
useRef,
useState,
- useMemo,
- useId,
} from 'react'
import {isValidElementType} from 'react-is'
import {ActionStateDialog} from './ActionStateDialog'
-import {DocumentActionDescription, Hotkeys, LegacyLayerProvider} from 'sanity'
+import {DocumentActionDescription, Hotkeys, LegacyLayerProvider, useTranslation} from 'sanity'
+import {deskLocaleNamespace} from '../../../i18n'
export interface ActionMenuButtonProps {
actionStates: DocumentActionDescription[]
@@ -49,6 +50,7 @@ export function ActionMenuButton(props: ActionMenuButtonProps) {
)
const currentAction = actionStates[actionIndex]
+ const {t} = useTranslation(deskLocaleNamespace)
return (
<>
@@ -57,7 +59,7 @@ export function ActionMenuButton(props: ActionMenuButtonProps) {
button={