Skip to content

Commit

Permalink
feat(i18n): adds translation for desk panes (#5085)
Browse files Browse the repository at this point in the history
  • Loading branch information
jtpetty authored and bjoerge committed Nov 6, 2023
1 parent b9a28bf commit 62e6102
Show file tree
Hide file tree
Showing 21 changed files with 418 additions and 127 deletions.
3 changes: 3 additions & 0 deletions packages/sanity/src/core/i18n/bundles/studio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
157 changes: 157 additions & 0 deletions packages/sanity/src/desk/i18n/resources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 <Code>{{id}}</Code> 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: <Code>{{documentType}}</Code>',

/** 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 <Code>{{documentType}}</Code>, 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: <Code>{{error}}</Code>',

/** 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 */
Expand All @@ -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 <Code>{{type}}</Code> is not a known entity.',

/** The title of the unknown pane */
'panes.unknown-pane-type.title': 'Unknown pane type',
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -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']

Expand All @@ -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
Expand All @@ -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>
<summary>Details</summary>
<summary>{t('panes.document-operation-results.error.summary.title')}</summary>
{event.error.message}
</details>
),
Expand All @@ -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}),
})
}

Expand All @@ -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
})
48 changes: 36 additions & 12 deletions packages/sanity/src/desk/panes/document/DocumentPane.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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'

Expand Down Expand Up @@ -119,8 +122,17 @@ function DocumentPaneInner(props: DocumentPaneProviderProps) {
: {path: [], state: 'none'}
}, [parentRefPath, groupIndex, routerPanesStateLength])

const {t} = useTranslation(deskLocaleNamespace)

if (options.type === '*' && !isLoaded) {
return <LoadingPane flex={2.5} minWidth={320} paneKey={paneKey} title="Loading document…" />
return (
<LoadingPane
flex={2.5}
minWidth={320}
paneKey={paneKey}
title={t('panes.document-pane.document-not-found.loading')}
/>
)
}

if (!documentType) {
Expand All @@ -129,12 +141,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')}
>
<Stack space={4}>
<Text as="p">
The document type is not defined, and a document with the <code>{options.id}</code>{' '}
identifier could not be found.
<Translate
t={t}
i18nKey="panes.document-pane.document-not-found.text"
components={{Code: ({children}) => <code>{children}</code>}}
values={{id: options.id}}
/>
</Text>
</Stack>
</ErrorPane>
Expand Down Expand Up @@ -241,6 +257,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 (
Expand All @@ -250,27 +267,33 @@ function InnerDocumentPane() {
minWidth={minWidth}
paneKey={paneKey}
title={
<>
Unknown document type: <code>{documentType}</code>
</>
<Translate
t={t}
i18nKey="panes.document-pane.document-unknown-type.title"
components={{Code: ({children}) => <code>{children}</code>}}
values={{documentType}}
/>
}
tone="caution"
>
<Stack space={4}>
{documentType && (
<Text as="p">
This document has the schema type <code>{documentType}</code>, which is not defined as
a type in the local content studio schema.
<Translate
t={t}
i18nKey="panes.document-pane.document-unknown-type.text"
components={{Code: ({children}) => <code>{children}</code>}}
values={{documentType}}
/>
</Text>
)}

{!documentType && (
<Text as="p">
This document does not exist, and no schema type was specified for it.
</Text>
<Text as="p">{t('panes.document-pane.document-unknown-type.without-schema.text')}</Text>
)}

{isDev && value && (
/* eslint-disable i18next/no-literal-string */
<>
<Text as="p">Here is the JSON representation of the document:</Text>
<Card padding={3} overflow="auto" radius={2} shadow={1} tone="inherit">
Expand All @@ -279,6 +302,7 @@ function InnerDocumentPane() {
</Code>
</Card>
</>
/* eslint-enable i18next/no-literal-string */
)}
</Stack>
</ErrorPane>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -644,10 +644,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])

// Reset `focusPath` when `documentId` or `params.path` changes
useEffect(() => {
Expand Down
Loading

0 comments on commit 62e6102

Please sign in to comment.