Skip to content

Commit 3127d6a

Browse files
authored
fix(plugin-import-export): add translations for all UI elements and fields (#12449)
Converts all text and field labels into variables that can be translated. Also generated the translations for them So now the UI here is internationalised ![image](https://github.com/user-attachments/assets/40d7c010-ac58-4cd7-8786-01b3de3cabb7) I've also moved some of the generic labels into the core package since those could be re-used elsewhere
1 parent 72ab319 commit 3127d6a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

98 files changed

+1704
-74
lines changed

packages/plugin-import-export/package.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,16 @@
4242
"import": "./src/exports/rsc.ts",
4343
"types": "./src/exports/rsc.ts",
4444
"default": "./src/exports/rsc.ts"
45+
},
46+
"./translations/languages/all": {
47+
"import": "./src/translations/index.ts",
48+
"types": "./src/translations/index.ts",
49+
"default": "./src/translations/index.ts"
50+
},
51+
"./translations/languages/*": {
52+
"import": "./src/translations/languages/*.ts",
53+
"types": "./src/translations/languages/*.ts",
54+
"default": "./src/translations/languages/*.ts"
4555
}
4656
},
4757
"main": "./src/index.ts",
@@ -92,6 +102,16 @@
92102
"import": "./dist/exports/rsc.js",
93103
"types": "./dist/exports/rsc.d.ts",
94104
"default": "./dist/exports/rsc.js"
105+
},
106+
"./translations/languages/all": {
107+
"import": "./dist/translations/index.js",
108+
"types": "./dist/translations/index.d.ts",
109+
"default": "./dist/translations/index.js"
110+
},
111+
"./translations/languages/*": {
112+
"import": "./dist/translations/languages/*.js",
113+
"types": "./dist/translations/languages/*.d.ts",
114+
"default": "./dist/translations/languages/*.js"
95115
}
96116
},
97117
"main": "./dist/index.js",

packages/plugin-import-export/src/components/ExportListMenuItem/index.tsx

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,20 @@
11
'use client'
22

33
import { getTranslation } from '@payloadcms/translations'
4-
import { PopupList, useConfig, useDocumentDrawer, useTranslation } from '@payloadcms/ui'
4+
import {
5+
PopupList,
6+
Translation,
7+
useConfig,
8+
useDocumentDrawer,
9+
useTranslation,
10+
} from '@payloadcms/ui'
511
import React, { useEffect } from 'react'
612

13+
import type {
14+
PluginImportExportTranslationKeys,
15+
PluginImportExportTranslations,
16+
} from '../../translations/index.js'
17+
718
import { useImportExport } from '../ImportExportProvider/index.js'
819
import './index.scss'
920

@@ -14,7 +25,10 @@ export const ExportListMenuItem: React.FC<{
1425
exportCollectionSlug: string
1526
}> = ({ collectionSlug, exportCollectionSlug }) => {
1627
const { getEntityConfig } = useConfig()
17-
const { i18n } = useTranslation()
28+
const { i18n, t } = useTranslation<
29+
PluginImportExportTranslations,
30+
PluginImportExportTranslationKeys
31+
>()
1832
const currentCollectionConfig = getEntityConfig({ collectionSlug })
1933

2034
const [DocumentDrawer, DocumentDrawerToggler] = useDocumentDrawer({
@@ -30,7 +44,15 @@ export const ExportListMenuItem: React.FC<{
3044
return (
3145
<PopupList.Button className={baseClass}>
3246
<DocumentDrawerToggler>
33-
Export {getTranslation(currentCollectionConfig.labels.plural, i18n)}
47+
<Translation
48+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
49+
// @ts-expect-error
50+
i18nKey="plugin-import-export:exportDocumentLabel"
51+
t={t}
52+
variables={{
53+
label: getTranslation(currentCollectionConfig.labels.plural, i18n),
54+
}}
55+
/>
3456
</DocumentDrawerToggler>
3557
<DocumentDrawer />
3658
</PopupList.Button>

packages/plugin-import-export/src/components/ExportSaveButton/index.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
'use client'
22

3-
import { Button, SaveButton, useConfig, useForm, useTranslation } from '@payloadcms/ui'
3+
import { Button, SaveButton, Translation, useConfig, useForm, useTranslation } from '@payloadcms/ui'
44
import React from 'react'
55

6+
import type {
7+
PluginImportExportTranslationKeys,
8+
PluginImportExportTranslations,
9+
} from '../../translations/index.js'
10+
611
export const ExportSaveButton: React.FC = () => {
7-
const { t } = useTranslation()
12+
const { t } = useTranslation<PluginImportExportTranslations, PluginImportExportTranslationKeys>()
813
const {
914
config: {
1015
routes: { api },
@@ -65,7 +70,7 @@ export const ExportSaveButton: React.FC = () => {
6570
<React.Fragment>
6671
<SaveButton label={label}></SaveButton>
6772
<Button onClick={handleDownload} size="medium" type="button">
68-
Download
73+
<Translation i18nKey="upload:download" t={t} />
6974
</Button>
7075
</React.Fragment>
7176
)

packages/plugin-import-export/src/components/FieldsToExport/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,12 @@ export const FieldsToExport: SelectFieldClientComponent = (props) => {
8383

8484
return (
8585
<div className={baseClass}>
86-
<FieldLabel label="Columns to Export" />
86+
<FieldLabel label={props.field.label} path={props.path} />
8787
<ReactSelect
8888
className={baseClass}
8989
disabled={props.readOnly}
9090
getOptionValue={(option) => String(option.value)}
91+
inputId={`field-${props.path.replace(/\./g, '__')}`}
9192
isClearable={true}
9293
isMulti={true}
9394
isSortable={true}

packages/plugin-import-export/src/components/Preview/index.tsx

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,18 @@ import type { Column } from '@payloadcms/ui'
33
import type { ClientField, FieldAffectingDataClient } from 'payload'
44

55
import { getTranslation } from '@payloadcms/translations'
6-
import { Table, useConfig, useField, useTranslation } from '@payloadcms/ui'
6+
import { Table, Translation, useConfig, useField, useTranslation } from '@payloadcms/ui'
77
import { fieldAffectsData } from 'payload/shared'
88
import * as qs from 'qs-esm'
99
import React from 'react'
1010

11-
import { useImportExport } from '../ImportExportProvider/index.js'
11+
import type {
12+
PluginImportExportTranslationKeys,
13+
PluginImportExportTranslations,
14+
} from '../../translations/index.js'
15+
1216
import './index.scss'
17+
import { useImportExport } from '../ImportExportProvider/index.js'
1318

1419
const baseClass = 'preview'
1520

@@ -24,7 +29,10 @@ export const Preview = () => {
2429
const [dataToRender, setDataToRender] = React.useState<any[]>([])
2530
const [resultCount, setResultCount] = React.useState<any>('')
2631
const [columns, setColumns] = React.useState<Column[]>([])
27-
const { i18n } = useTranslation()
32+
const { i18n, t } = useTranslation<
33+
PluginImportExportTranslations,
34+
PluginImportExportTranslationKeys
35+
>()
2836

2937
const collectionSlug = typeof collection === 'string' && collection
3038
const collectionConfig = config.collections.find(
@@ -102,8 +110,20 @@ export const Preview = () => {
102110
return (
103111
<div className={baseClass}>
104112
<div className={`${baseClass}__header`}>
105-
<h3>Preview</h3>
106-
{resultCount && <span>{resultCount} total documents</span>}
113+
<h3>
114+
<Translation i18nKey="version:preview" t={t} />
115+
</h3>
116+
{resultCount && (
117+
<Translation
118+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
119+
// @ts-expect-error
120+
i18nKey="plugin-import-export:totalDocumentsCount"
121+
t={t}
122+
variables={{
123+
count: resultCount,
124+
}}
125+
/>
126+
)}
107127
</div>
108128
{dataToRender && <Table columns={columns} data={dataToRender} />}
109129
</div>

packages/plugin-import-export/src/components/SortBy/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,12 @@ export const SortBy: SelectFieldClientComponent = (props) => {
7272

7373
return (
7474
<div className={baseClass} style={{ '--field-width': '33%' } as React.CSSProperties}>
75-
<FieldLabel label="Sort By" />
75+
<FieldLabel label={props.field.label} path={props.path} />
7676
<ReactSelect
7777
className={baseClass}
7878
disabled={props.readOnly}
7979
getOptionValue={(option) => String(option.value)}
80+
inputId={`field-${props.path.replace(/\./g, '__')}`}
8081
isClearable={true}
8182
isSortable={true}
8283
// @ts-expect-error react select option

packages/plugin-import-export/src/export/getFields.ts

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@ export const getFields = (config: Config): Field[] => {
1212
width: '33%',
1313
},
1414
defaultValue: 'all',
15-
label: 'Locale',
15+
// @ts-expect-error - this is not correctly typed in plugins right now
16+
label: ({ t }) => t('plugin-import-export:field-locale-label'),
1617
options: [
1718
{
18-
label: 'All Locales',
19+
label: ({ t }) => t('general:allLocales'),
1920
value: 'all',
2021
},
2122
...config.localization.locales.map((locale) => ({
@@ -34,7 +35,8 @@ export const getFields = (config: Config): Field[] => {
3435
name: 'name',
3536
type: 'text',
3637
defaultValue: () => getFilename(),
37-
label: 'File Name',
38+
// @ts-expect-error - this is not correctly typed in plugins right now
39+
label: ({ t }) => t('plugin-import-export:field-name-label'),
3840
},
3941
{
4042
type: 'row',
@@ -46,7 +48,8 @@ export const getFields = (config: Config): Field[] => {
4648
width: '33%',
4749
},
4850
defaultValue: 'csv',
49-
label: 'Export Format',
51+
// @ts-expect-error - this is not correctly typed in plugins right now
52+
label: ({ t }) => t('plugin-import-export:field-format-label'),
5053
options: [
5154
{
5255
label: 'CSV',
@@ -66,6 +69,8 @@ export const getFields = (config: Config): Field[] => {
6669
placeholder: 'No limit',
6770
width: '33%',
6871
},
72+
// @ts-expect-error - this is not correctly typed in plugins right now
73+
label: ({ t }) => t('plugin-import-export:field-limit-label'),
6974
},
7075
{
7176
name: 'sort',
@@ -75,6 +80,8 @@ export const getFields = (config: Config): Field[] => {
7580
Field: '@payloadcms/plugin-import-export/rsc#SortBy',
7681
},
7782
},
83+
// @ts-expect-error - this is not correctly typed in plugins right now
84+
label: ({ t }) => t('plugin-import-export:field-sort-label'),
7885
},
7986
],
8087
},
@@ -98,21 +105,24 @@ export const getFields = (config: Config): Field[] => {
98105
width: '33%',
99106
},
100107
defaultValue: 'yes',
101-
label: 'Drafts',
108+
// @ts-expect-error - this is not correctly typed in plugins right now
109+
label: ({ t }) => t('plugin-import-export:field-drafts-label'),
102110
options: [
103111
{
104-
label: 'Yes',
112+
label: ({ t }) => t('general:yes'),
105113
value: 'yes',
106114
},
107115
{
108-
label: 'No',
116+
label: ({ t }) => t('general:no'),
109117
value: 'no',
110118
},
111119
],
112120
},
113121
// {
114122
// name: 'depth',
115123
// type: 'number',
124+
// // @ts-expect-error - this is not correctly typed in plugins right now
125+
// label: ({ t }) => t('plugin-import-export:field-depth-label'),
116126
// admin: {
117127
// width: '33%',
118128
// },
@@ -126,17 +136,22 @@ export const getFields = (config: Config): Field[] => {
126136
name: 'selectionToUse',
127137
type: 'radio',
128138
defaultValue: 'all',
139+
// @ts-expect-error - this is not correctly typed in plugins right now
140+
label: ({ t }) => t('plugin-import-export:field-selectionToUse-label'),
129141
options: [
130142
{
131-
label: 'Use current selection',
143+
// @ts-expect-error - this is not correctly typed in plugins right now
144+
label: ({ t }) => t('plugin-import-export:selectionToUse-currentSelection'),
132145
value: 'currentSelection',
133146
},
134147
{
135-
label: 'Use current filters',
148+
// @ts-expect-error - this is not correctly typed in plugins right now
149+
label: ({ t }) => t('plugin-import-export:selectionToUse-currentFilters'),
136150
value: 'currentFilters',
137151
},
138152
{
139-
label: 'Use all documents',
153+
// @ts-expect-error - this is not correctly typed in plugins right now
154+
label: ({ t }) => t('plugin-import-export:selectionToUse-allDocuments'),
140155
value: 'all',
141156
},
142157
],
@@ -151,6 +166,8 @@ export const getFields = (config: Config): Field[] => {
151166
},
152167
},
153168
hasMany: true,
169+
// @ts-expect-error - this is not correctly typed in plugins right now
170+
label: ({ t }) => t('plugin-import-export:field-fields-label'),
154171
},
155172
{
156173
name: 'collectionSlug',
@@ -174,7 +191,8 @@ export const getFields = (config: Config): Field[] => {
174191
defaultValue: {},
175192
},
176193
],
177-
label: 'Export Options',
194+
// @ts-expect-error - this is not correctly typed in plugins right now
195+
label: ({ t }) => t('plugin-import-export:exportOptions'),
178196
},
179197
{
180198
name: 'preview',

packages/plugin-import-export/src/index.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { Config, JobsConfig } from 'payload'
22

33
import { deepMergeSimple } from 'payload'
44

5+
import type { PluginDefaultTranslationsObject } from './translations/types.js'
56
import type { ImportExportPluginConfig } from './types.js'
67

78
import { getCreateCollectionExportTask } from './export/getCreateExportCollectionTask.js'
@@ -70,7 +71,23 @@ export const importExportPlugin =
7071
config.i18n = {}
7172
}
7273

73-
config.i18n.translations = deepMergeSimple(translations, config.i18n?.translations ?? {})
74+
// config.i18n.translations = deepMergeSimple(translations, config.i18n?.translations ?? {})
75+
76+
/**
77+
* Merge plugin translations
78+
*/
79+
const simplifiedTranslations = Object.entries(translations).reduce(
80+
(acc, [key, value]) => {
81+
acc[key] = value.translations
82+
return acc
83+
},
84+
{} as Record<string, PluginDefaultTranslationsObject>,
85+
)
86+
87+
config.i18n = {
88+
...config.i18n,
89+
translations: deepMergeSimple(simplifiedTranslations, config.i18n?.translations ?? {}),
90+
}
7491

7592
return config
7693
}

packages/plugin-import-export/src/translations/en.ts

Lines changed: 0 additions & 9 deletions
This file was deleted.

0 commit comments

Comments
 (0)