Skip to content

Commit 31211e9

Browse files
authored
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)}` // ... } ] } ```
1 parent 032c424 commit 31211e9

File tree

12 files changed

+29
-24
lines changed

12 files changed

+29
-24
lines changed

packages/next/src/views/Versions/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ export async function VersionsView(props: DocumentViewServerProps) {
172172

173173
const pluralLabel = collectionConfig?.labels?.plural
174174
? typeof collectionConfig.labels.plural === 'function'
175-
? collectionConfig.labels.plural({ t })
175+
? collectionConfig.labels.plural({ i18n, t })
176176
: collectionConfig.labels.plural
177177
: globalConfig?.label
178178

packages/payload/src/admin/forms/Description.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import type { TFunction } from '@payloadcms/translations'
1+
import type { I18nClient, TFunction } from '@payloadcms/translations'
22

33
import type { Field } from '../../fields/config/types.js'
44
import type { ClientFieldWithOptionalType, ServerComponentProps } from './Field.js'
55

6-
export type DescriptionFunction = ({ t }: { t: TFunction }) => string
6+
export type DescriptionFunction = (args: { i18n: I18nClient; t: TFunction }) => string
77

88
export type FieldDescriptionClientComponent<
99
TFieldClient extends ClientFieldWithOptionalType = ClientFieldWithOptionalType,

packages/payload/src/collections/config/client.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,11 +215,11 @@ export const createClientCollectionConfig = ({
215215
clientCollection.labels = {
216216
plural:
217217
typeof collection.labels.plural === 'function'
218-
? collection.labels.plural({ t: i18n.t })
218+
? collection.labels.plural({ i18n, t: i18n.t })
219219
: collection.labels.plural,
220220
singular:
221221
typeof collection.labels.singular === 'function'
222-
? collection.labels.singular({ t: i18n.t })
222+
? collection.labels.singular({ i18n, t: i18n.t })
223223
: collection.labels.singular,
224224
}
225225
break

packages/payload/src/config/types.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -508,9 +508,8 @@ export type LocalizationConfig = Prettify<
508508
LocalizationConfigWithLabels | LocalizationConfigWithNoLabels
509509
>
510510

511-
export type LabelFunction<TTranslationKeys = DefaultTranslationKeys> = ({
512-
t,
513-
}: {
511+
export type LabelFunction<TTranslationKeys = DefaultTranslationKeys> = (args: {
512+
i18n: I18nClient
514513
t: TFunction<TTranslationKeys>
515514
}) => string
516515

packages/payload/src/fields/config/client.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -140,12 +140,12 @@ export const createClientBlocks = ({
140140

141141
if (block.labels.singular) {
142142
if (typeof block.labels.singular === 'function') {
143-
clientBlock.labels.singular = block.labels.singular({ t: i18n.t })
143+
clientBlock.labels.singular = block.labels.singular({ i18n, t: i18n.t })
144144
} else {
145145
clientBlock.labels.singular = block.labels.singular
146146
}
147147
if (typeof block.labels.plural === 'function') {
148-
clientBlock.labels.plural = block.labels.plural({ t: i18n.t })
148+
clientBlock.labels.plural = block.labels.plural({ i18n, t: i18n.t })
149149
} else {
150150
clientBlock.labels.plural = block.labels.plural
151151
}
@@ -224,7 +224,7 @@ export const createClientField = ({
224224
//@ts-expect-error - would need to type narrow
225225
if (typeof incomingField.label === 'function') {
226226
//@ts-expect-error - would need to type narrow
227-
clientField.label = incomingField.label({ t: i18n.t })
227+
clientField.label = incomingField.label({ i18n, t: i18n.t })
228228
} else {
229229
//@ts-expect-error - would need to type narrow
230230
clientField.label = incomingField.label
@@ -246,12 +246,12 @@ export const createClientField = ({
246246

247247
if (incomingField.labels.singular) {
248248
if (typeof incomingField.labels.singular === 'function') {
249-
field.labels.singular = incomingField.labels.singular({ t: i18n.t })
249+
field.labels.singular = incomingField.labels.singular({ i18n, t: i18n.t })
250250
} else {
251251
field.labels.singular = incomingField.labels.singular
252252
}
253253
if (typeof incomingField.labels.plural === 'function') {
254-
field.labels.plural = incomingField.labels.plural({ t: i18n.t })
254+
field.labels.plural = incomingField.labels.plural({ i18n, t: i18n.t })
255255
} else {
256256
field.labels.plural = incomingField.labels.plural
257257
}
@@ -287,12 +287,12 @@ export const createClientField = ({
287287

288288
if (incomingField.labels.singular) {
289289
if (typeof incomingField.labels.singular === 'function') {
290-
field.labels.singular = incomingField.labels.singular({ t: i18n.t })
290+
field.labels.singular = incomingField.labels.singular({ i18n, t: i18n.t })
291291
} else {
292292
field.labels.singular = incomingField.labels.singular
293293
}
294294
if (typeof incomingField.labels.plural === 'function') {
295-
field.labels.plural = incomingField.labels.plural({ t: i18n.t })
295+
field.labels.plural = incomingField.labels.plural({ i18n, t: i18n.t })
296296
} else {
297297
field.labels.plural = incomingField.labels.plural
298298
}
@@ -345,7 +345,7 @@ export const createClientField = ({
345345
}
346346

347347
field.options[i] = {
348-
label: option.label({ t: i18n.t }),
348+
label: option.label({ i18n, t: i18n.t }),
349349
value: option.value,
350350
}
351351
}
@@ -409,7 +409,7 @@ export const createClientField = ({
409409
case 'description':
410410
if ('description' in tab.admin) {
411411
if (typeof tab.admin?.description === 'function') {
412-
clientTab.admin.description = tab.admin.description({ t: i18n.t })
412+
clientTab.admin.description = tab.admin.description({ i18n, t: i18n.t })
413413
} else {
414414
clientTab.admin.description = tab.admin.description
415415
}

packages/payload/src/fields/config/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,7 @@ export type OptionObject = {
447447
label: OptionLabel
448448
value: string
449449
}
450+
450451
export type Option = OptionObject | string
451452

452453
export type FieldGraphQLType = {

packages/payload/src/globals/config/client.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ export const createClientGlobalConfig = ({
105105
break
106106
case 'label':
107107
clientGlobal.label =
108-
typeof global.label === 'function' ? global.label({ t: i18n.t }) : global.label
108+
typeof global.label === 'function' ? global.label({ i18n, t: i18n.t }) : global.label
109109
break
110110
default: {
111111
clientGlobal[key] = global[key]

packages/payload/src/utilities/getTranslatedLabel.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import type { LabelFunction, StaticLabel } from '../config/types.js'
55

66
export const getTranslatedLabel = (label: LabelFunction | StaticLabel, i18n?: I18n): string => {
77
if (typeof label === 'function') {
8-
return label({ t: i18n.t })
8+
return label({ i18n, t: i18n.t })
99
}
1010

1111
if (typeof label === 'object') {

packages/translations/src/utilities/getTranslation.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import type { JSX } from 'react'
22

3-
import type { I18n, TFunction } from '../types.js'
3+
import type { I18n, I18nClient, TFunction } from '../types.js'
44

55
type LabelType =
66
| (() => JSX.Element)
7-
| (({ t }: { t: TFunction }) => string)
7+
| ((args: { i18n: I18nClient; t: TFunction }) => string)
88
| JSX.Element
99
| Record<string, string>
1010
| string
@@ -35,7 +35,9 @@ export const getTranslation = <T extends LabelType>(
3535
}
3636

3737
if (typeof label === 'function') {
38-
return label({ t: i18n.t }) as unknown as T extends JSX.Element ? JSX.Element : string
38+
return label({ i18n: undefined as any, t: i18n.t }) as unknown as T extends JSX.Element
39+
? JSX.Element
40+
: string
3941
}
4042

4143
// If it's a React Element or string, then we should just pass it through

packages/ui/src/fields/Tabs/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ const TabsFieldComponent: TabsFieldClientComponent = (props) => {
9898

9999
const activeTabStaticDescription =
100100
typeof activeTabDescription === 'function'
101-
? activeTabDescription({ t: i18n.t })
101+
? activeTabDescription({ i18n, t: i18n.t })
102102
: activeTabDescription
103103

104104
const hasVisibleTabs = tabStates.some(({ passesCondition }) => passesCondition)

0 commit comments

Comments
 (0)