feat: pass i18n through field label and description functions (#11802)
Passes the `i18n` arg through field label and description functions.
This is to avoid using custom components when simply needing to
translate a `StaticLabel` object, such as collection labels.
Here's an example:
```ts
{
labels: {
singular: {
en: 'My Collection'
}
},
fields: [
// ...
{
type: 'collapsible',
label: ({ i18n }) => `Translate this: ${getTranslation(collectionConfig.labels.singular, i18n)}`
// ...
}
]
}
```
This commit is contained in:
@@ -172,7 +172,7 @@ export async function VersionsView(props: DocumentViewServerProps) {
|
||||
|
||||
const pluralLabel = collectionConfig?.labels?.plural
|
||||
? typeof collectionConfig.labels.plural === 'function'
|
||||
? collectionConfig.labels.plural({ t })
|
||||
? collectionConfig.labels.plural({ i18n, t })
|
||||
: collectionConfig.labels.plural
|
||||
: globalConfig?.label
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import type { TFunction } from '@payloadcms/translations'
|
||||
import type { I18nClient, TFunction } from '@payloadcms/translations'
|
||||
|
||||
import type { Field } from '../../fields/config/types.js'
|
||||
import type { ClientFieldWithOptionalType, ServerComponentProps } from './Field.js'
|
||||
|
||||
export type DescriptionFunction = ({ t }: { t: TFunction }) => string
|
||||
export type DescriptionFunction = (args: { i18n: I18nClient; t: TFunction }) => string
|
||||
|
||||
export type FieldDescriptionClientComponent<
|
||||
TFieldClient extends ClientFieldWithOptionalType = ClientFieldWithOptionalType,
|
||||
|
||||
@@ -215,11 +215,11 @@ export const createClientCollectionConfig = ({
|
||||
clientCollection.labels = {
|
||||
plural:
|
||||
typeof collection.labels.plural === 'function'
|
||||
? collection.labels.plural({ t: i18n.t })
|
||||
? collection.labels.plural({ i18n, t: i18n.t })
|
||||
: collection.labels.plural,
|
||||
singular:
|
||||
typeof collection.labels.singular === 'function'
|
||||
? collection.labels.singular({ t: i18n.t })
|
||||
? collection.labels.singular({ i18n, t: i18n.t })
|
||||
: collection.labels.singular,
|
||||
}
|
||||
break
|
||||
|
||||
@@ -508,9 +508,8 @@ export type LocalizationConfig = Prettify<
|
||||
LocalizationConfigWithLabels | LocalizationConfigWithNoLabels
|
||||
>
|
||||
|
||||
export type LabelFunction<TTranslationKeys = DefaultTranslationKeys> = ({
|
||||
t,
|
||||
}: {
|
||||
export type LabelFunction<TTranslationKeys = DefaultTranslationKeys> = (args: {
|
||||
i18n: I18nClient
|
||||
t: TFunction<TTranslationKeys>
|
||||
}) => string
|
||||
|
||||
|
||||
@@ -140,12 +140,12 @@ export const createClientBlocks = ({
|
||||
|
||||
if (block.labels.singular) {
|
||||
if (typeof block.labels.singular === 'function') {
|
||||
clientBlock.labels.singular = block.labels.singular({ t: i18n.t })
|
||||
clientBlock.labels.singular = block.labels.singular({ i18n, t: i18n.t })
|
||||
} else {
|
||||
clientBlock.labels.singular = block.labels.singular
|
||||
}
|
||||
if (typeof block.labels.plural === 'function') {
|
||||
clientBlock.labels.plural = block.labels.plural({ t: i18n.t })
|
||||
clientBlock.labels.plural = block.labels.plural({ i18n, t: i18n.t })
|
||||
} else {
|
||||
clientBlock.labels.plural = block.labels.plural
|
||||
}
|
||||
@@ -224,7 +224,7 @@ export const createClientField = ({
|
||||
//@ts-expect-error - would need to type narrow
|
||||
if (typeof incomingField.label === 'function') {
|
||||
//@ts-expect-error - would need to type narrow
|
||||
clientField.label = incomingField.label({ t: i18n.t })
|
||||
clientField.label = incomingField.label({ i18n, t: i18n.t })
|
||||
} else {
|
||||
//@ts-expect-error - would need to type narrow
|
||||
clientField.label = incomingField.label
|
||||
@@ -246,12 +246,12 @@ export const createClientField = ({
|
||||
|
||||
if (incomingField.labels.singular) {
|
||||
if (typeof incomingField.labels.singular === 'function') {
|
||||
field.labels.singular = incomingField.labels.singular({ t: i18n.t })
|
||||
field.labels.singular = incomingField.labels.singular({ i18n, t: i18n.t })
|
||||
} else {
|
||||
field.labels.singular = incomingField.labels.singular
|
||||
}
|
||||
if (typeof incomingField.labels.plural === 'function') {
|
||||
field.labels.plural = incomingField.labels.plural({ t: i18n.t })
|
||||
field.labels.plural = incomingField.labels.plural({ i18n, t: i18n.t })
|
||||
} else {
|
||||
field.labels.plural = incomingField.labels.plural
|
||||
}
|
||||
@@ -287,12 +287,12 @@ export const createClientField = ({
|
||||
|
||||
if (incomingField.labels.singular) {
|
||||
if (typeof incomingField.labels.singular === 'function') {
|
||||
field.labels.singular = incomingField.labels.singular({ t: i18n.t })
|
||||
field.labels.singular = incomingField.labels.singular({ i18n, t: i18n.t })
|
||||
} else {
|
||||
field.labels.singular = incomingField.labels.singular
|
||||
}
|
||||
if (typeof incomingField.labels.plural === 'function') {
|
||||
field.labels.plural = incomingField.labels.plural({ t: i18n.t })
|
||||
field.labels.plural = incomingField.labels.plural({ i18n, t: i18n.t })
|
||||
} else {
|
||||
field.labels.plural = incomingField.labels.plural
|
||||
}
|
||||
@@ -345,7 +345,7 @@ export const createClientField = ({
|
||||
}
|
||||
|
||||
field.options[i] = {
|
||||
label: option.label({ t: i18n.t }),
|
||||
label: option.label({ i18n, t: i18n.t }),
|
||||
value: option.value,
|
||||
}
|
||||
}
|
||||
@@ -409,7 +409,7 @@ export const createClientField = ({
|
||||
case 'description':
|
||||
if ('description' in tab.admin) {
|
||||
if (typeof tab.admin?.description === 'function') {
|
||||
clientTab.admin.description = tab.admin.description({ t: i18n.t })
|
||||
clientTab.admin.description = tab.admin.description({ i18n, t: i18n.t })
|
||||
} else {
|
||||
clientTab.admin.description = tab.admin.description
|
||||
}
|
||||
|
||||
@@ -447,6 +447,7 @@ export type OptionObject = {
|
||||
label: OptionLabel
|
||||
value: string
|
||||
}
|
||||
|
||||
export type Option = OptionObject | string
|
||||
|
||||
export type FieldGraphQLType = {
|
||||
|
||||
@@ -105,7 +105,7 @@ export const createClientGlobalConfig = ({
|
||||
break
|
||||
case 'label':
|
||||
clientGlobal.label =
|
||||
typeof global.label === 'function' ? global.label({ t: i18n.t }) : global.label
|
||||
typeof global.label === 'function' ? global.label({ i18n, t: i18n.t }) : global.label
|
||||
break
|
||||
default: {
|
||||
clientGlobal[key] = global[key]
|
||||
|
||||
@@ -5,7 +5,7 @@ import type { LabelFunction, StaticLabel } from '../config/types.js'
|
||||
|
||||
export const getTranslatedLabel = (label: LabelFunction | StaticLabel, i18n?: I18n): string => {
|
||||
if (typeof label === 'function') {
|
||||
return label({ t: i18n.t })
|
||||
return label({ i18n, t: i18n.t })
|
||||
}
|
||||
|
||||
if (typeof label === 'object') {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import type { JSX } from 'react'
|
||||
|
||||
import type { I18n, TFunction } from '../types.js'
|
||||
import type { I18n, I18nClient, TFunction } from '../types.js'
|
||||
|
||||
type LabelType =
|
||||
| (() => JSX.Element)
|
||||
| (({ t }: { t: TFunction }) => string)
|
||||
| ((args: { i18n: I18nClient; t: TFunction }) => string)
|
||||
| JSX.Element
|
||||
| Record<string, string>
|
||||
| string
|
||||
@@ -35,7 +35,9 @@ export const getTranslation = <T extends LabelType>(
|
||||
}
|
||||
|
||||
if (typeof label === 'function') {
|
||||
return label({ t: i18n.t }) as unknown as T extends JSX.Element ? JSX.Element : string
|
||||
return label({ i18n: undefined as any, t: i18n.t }) as unknown as T extends JSX.Element
|
||||
? JSX.Element
|
||||
: string
|
||||
}
|
||||
|
||||
// If it's a React Element or string, then we should just pass it through
|
||||
|
||||
@@ -98,7 +98,7 @@ const TabsFieldComponent: TabsFieldClientComponent = (props) => {
|
||||
|
||||
const activeTabStaticDescription =
|
||||
typeof activeTabDescription === 'function'
|
||||
? activeTabDescription({ t: i18n.t })
|
||||
? activeTabDescription({ i18n, t: i18n.t })
|
||||
: activeTabDescription
|
||||
|
||||
const hasVisibleTabs = tabStates.some(({ passesCondition }) => passesCondition)
|
||||
|
||||
@@ -244,6 +244,7 @@ export const renderField: RenderFieldMethod = ({
|
||||
fieldState.customComponents.Description = (
|
||||
<FieldDescription
|
||||
description={fieldConfig.admin?.description({
|
||||
i18n: req.i18n,
|
||||
t: req.i18n.t,
|
||||
})}
|
||||
path={path}
|
||||
|
||||
@@ -53,7 +53,9 @@ export function groupNavItems(
|
||||
: entityToGroup.entity.label
|
||||
|
||||
const label =
|
||||
typeof labelOrFunction === 'function' ? labelOrFunction({ t: i18n.t }) : labelOrFunction
|
||||
typeof labelOrFunction === 'function'
|
||||
? labelOrFunction({ i18n, t: i18n.t })
|
||||
: labelOrFunction
|
||||
|
||||
if (entityToGroup.entity.admin.group) {
|
||||
const existingGroup = groups.find(
|
||||
|
||||
Reference in New Issue
Block a user