@payload-enchants/translator 1.1.7 → 1.1.9
Sign up to get free protection for your applications and to get access to all the features.
- package/LICENSE +21 -21
- package/README.md +193 -193
- package/dist/client/api/index.js.map +1 -1
- package/dist/client/components/CustomSaveButton/CustomSaveButton.js.map +1 -1
- package/dist/client/components/CustomSaveButton/index.js.map +1 -1
- package/dist/client/components/CustomSaveButton/styles.scss +5 -5
- package/dist/client/components/LocaleLabel/LocaleLabel.js.map +1 -1
- package/dist/client/components/LocaleLabel/index.js.map +1 -1
- package/dist/client/components/ResolverButton/ResolverButton.js.map +1 -1
- package/dist/client/components/ResolverButton/index.js.map +1 -1
- package/dist/client/components/TranslatorModal/Content.js.map +1 -1
- package/dist/client/components/TranslatorModal/TranslatorModal.js.map +1 -1
- package/dist/client/components/TranslatorModal/index.js.map +1 -1
- package/dist/client/components/TranslatorModal/styles.scss +76 -76
- package/dist/client/providers/Translator/TranslatorProvider.js.map +1 -1
- package/dist/client/providers/Translator/context.js.map +1 -1
- package/dist/i18n-translations.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/resolvers/copy.js.map +1 -1
- package/dist/resolvers/google.js.map +1 -1
- package/dist/resolvers/openAI.js.map +1 -1
- package/dist/resolvers/types.js.map +1 -1
- package/dist/translate/endpoint.js.map +1 -1
- package/dist/translate/findEntityWithConfig.js.map +1 -1
- package/dist/translate/operation.js.map +1 -1
- package/dist/translate/traverseFields.js.map +1 -1
- package/dist/translate/traverseRichText.js.map +1 -1
- package/dist/translate/types.js.map +1 -1
- package/dist/translate/updateEntity.js.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/chunkArray.js.map +1 -1
- package/dist/utils/isEmpty.js.map +1 -1
- package/package.json +7 -7
package/LICENSE
CHANGED
@@ -1,21 +1,21 @@
|
|
1
|
-
MIT License
|
2
|
-
|
3
|
-
Copyright (c) 2024 Ritsu / Sasha Rakhmatulin
|
4
|
-
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
7
|
-
in the Software without restriction, including without limitation the rights
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
10
|
-
furnished to do so, subject to the following conditions:
|
11
|
-
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
13
|
-
copies or substantial portions of the Software.
|
14
|
-
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
-
SOFTWARE.
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2024 Ritsu / Sasha Rakhmatulin
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
@@ -1,193 +1,193 @@
|
|
1
|
-
# Translator plugin for Payload 3.0 (beta)
|
2
|
-
|
3
|
-
## Install
|
4
|
-
|
5
|
-
`pnpm add @payload-enchants/translator`
|
6
|
-
|
7
|
-
## Video
|
8
|
-
|
9
|
-
https://github.com/r1tsuu/payload-plugin-translator/assets/64744993/d39aeba4-bafc-4c3b-838e-9abc5cf1d64a
|
10
|
-
|
11
|
-
## Features:
|
12
|
-
|
13
|
-
1. A flexible structure with [resolvers](https://github.com/r1tsuu/payload-plugin-translator/tree/6d0c8098467f9b5e757bf9fd8cfe63ff5da68d5b/plugin/src/resolvers) that allows you to apply any kind of transformation to your localizated data.
|
14
|
-
2. Can be used not only from the admin panel, but within Local API as well. [Example of the hook](#example-of-the-hook-that-uses-local-operation-to-copy-the-doc-data-to-other-locales) that automatically fills the other locales data on create
|
15
|
-
3. Out of the box supports 3 resolvers - Copy, Google Translate, OpenAI and your own can be written easily.
|
16
|
-
4. Works with any nested document structure and 2 Rich Text editor adapters - Lexical and Slate.
|
17
|
-
|
18
|
-
## Usage:
|
19
|
-
|
20
|
-
```ts
|
21
|
-
import { buildConfig } from 'payload/config';
|
22
|
-
import { translator } from '@payload-enchants/translator';
|
23
|
-
import { copyResolver } from '@payload-enchants/translator/resolvers/copy';
|
24
|
-
import { googleResolver } from '@payload-enchants/translator/resolvers/google';
|
25
|
-
import { openAIResolver } from '@payload-enchants/translator/resolvers/openAI';
|
26
|
-
|
27
|
-
export default buildConfig({
|
28
|
-
plugins: [
|
29
|
-
translator({
|
30
|
-
// collections with the enabled translator in the admin UI
|
31
|
-
collections: ['posts', 'small-posts'],
|
32
|
-
// globals with the enabled translator in the admin UI
|
33
|
-
globals: [],
|
34
|
-
// add resolvers that you want to include, examples on how to write your own in ./plugin/src/resolvers
|
35
|
-
resolvers: [
|
36
|
-
copyResolver(),
|
37
|
-
googleResolver({
|
38
|
-
apiKey: process.env.GOOGLE_API_KEY!,
|
39
|
-
}),
|
40
|
-
openAIResolver({
|
41
|
-
apiKey: process.env.OPENAI_KEY!,
|
42
|
-
}),
|
43
|
-
],
|
44
|
-
}),
|
45
|
-
],
|
46
|
-
});
|
47
|
-
```
|
48
|
-
|
49
|
-
## Resolvers
|
50
|
-
|
51
|
-
### OpenAI
|
52
|
-
|
53
|
-
#### Config:
|
54
|
-
|
55
|
-
```ts
|
56
|
-
export type OpenAIResolverConfig = {
|
57
|
-
apiKey: string; // API key
|
58
|
-
chunkLength?: number; // How many texts to include into 1 request, default: 100
|
59
|
-
model?: string; // model, default: 'gpt-3.5-turbo'
|
60
|
-
promt?: OpenAIPrompt; // custom prompt
|
61
|
-
};
|
62
|
-
```
|
63
|
-
|
64
|
-
### Custom prompt:
|
65
|
-
|
66
|
-
```ts
|
67
|
-
export type OpenAIPrompt = (args: {
|
68
|
-
localeFrom: string;
|
69
|
-
localeTo: string;
|
70
|
-
texts: string[];
|
71
|
-
}) => string;
|
72
|
-
|
73
|
-
// Default
|
74
|
-
const defaultPromt: OpenAIPrompt = ({ localeFrom, localeTo, texts }) => {
|
75
|
-
return `Translate me the following array: ${JSON.stringify(texts)} in locale=${localeFrom} to locale ${localeTo}, respond me with the same array structure`;
|
76
|
-
};
|
77
|
-
```
|
78
|
-
|
79
|
-
### Google
|
80
|
-
|
81
|
-
#### Config:
|
82
|
-
|
83
|
-
```ts
|
84
|
-
export type GoogleResolverConfig = {
|
85
|
-
apiKey: string; // API key
|
86
|
-
chunkLength?: number; / /How many texts to include into 1 request, default: 100
|
87
|
-
};
|
88
|
-
```
|
89
|
-
|
90
|
-
### Writing your own
|
91
|
-
|
92
|
-
```ts
|
93
|
-
import type { TranslateResolver } from '@payload-enchants/translator/resolvers/types';
|
94
|
-
|
95
|
-
const myResolver: TranslateResolver = {
|
96
|
-
key: 'my',
|
97
|
-
resolve: async (args) => {
|
98
|
-
const { localeFrom, localeTo, req, texts } = args;
|
99
|
-
// here you can apply any kind of transformation to incoming texts, could be as well API call to a service.
|
100
|
-
const transformed = texts.map((each) => `${each} translated to ${localeTo}`);
|
101
|
-
|
102
|
-
return {
|
103
|
-
success: true,
|
104
|
-
translatedTexts: transformed,
|
105
|
-
};
|
106
|
-
},
|
107
|
-
};
|
108
|
-
|
109
|
-
export default buildConfig({
|
110
|
-
plugins: [
|
111
|
-
payloadPluginTranslator({
|
112
|
-
collections: ['posts', 'small-posts'],
|
113
|
-
globals: [],
|
114
|
-
resolvers: [myResolver],
|
115
|
-
}),
|
116
|
-
],
|
117
|
-
// apply translations that will be used for your resolver in the admin UI
|
118
|
-
i18n: {
|
119
|
-
supportedLanguages: { en },
|
120
|
-
translations: {
|
121
|
-
en: {
|
122
|
-
'plugin-translator': {
|
123
|
-
resolver_my_buttonLabel: 'Google Translate',
|
124
|
-
resolver_my_errorMessage: 'An error occurred when trying to translate the data',
|
125
|
-
resolver_my_modalTitle: 'Choose the locale to translate from',
|
126
|
-
resolver_my_submitButtonLabelEmpty: 'Translate only empty fields',
|
127
|
-
resolver_my_submitButtonLabelFull: 'Translate all',
|
128
|
-
resolver_my_successMessage: 'Successfully translated. Press "Save" to apply the changes.',
|
129
|
-
},
|
130
|
-
},
|
131
|
-
},
|
132
|
-
},
|
133
|
-
});
|
134
|
-
```
|
135
|
-
|
136
|
-
## Using the Local API
|
137
|
-
|
138
|
-
```ts
|
139
|
-
import { translateOperation } from '@payload-enchants/translator';
|
140
|
-
|
141
|
-
const translateResult = await translateOperation({
|
142
|
-
collectionSlug: 'posts', // or globalSlug if globals,
|
143
|
-
emptyOnly: false, // optional, should translate all the fields values or only fields that are empty, by default false.
|
144
|
-
id: postDefaultLocale.id, // pass the doc id if it's a collection
|
145
|
-
locale: 'de', // locale to translate to
|
146
|
-
localeFrom: 'en', // locale to translate from
|
147
|
-
payload, // payload instance, you can get it with getPayload or req.payload in hooks
|
148
|
-
req, // PayloadRequest, can be used instead of payload, more appreciable than payload if you have it
|
149
|
-
overrideAccess: false, //
|
150
|
-
resolver: 'copy', // pass resolver key
|
151
|
-
update: true, // optional, should update immediately or just return the translated result, default false
|
152
|
-
data: {}, // Optional, if you want to translate from your data passed here instead of the current doc, should be in "localeFrom" locale, for example { title: "Hello" }
|
153
|
-
});
|
154
|
-
```
|
155
|
-
|
156
|
-
### Example of the hook that uses local operation to copy the doc data to other locales
|
157
|
-
|
158
|
-
```ts
|
159
|
-
import type { CollectionAfterChangeHook } from 'payload/types';
|
160
|
-
import { translateOperation } from '@payload-enchants/translator';
|
161
|
-
|
162
|
-
export const copyOtherLocales: CollectionAfterChangeHook = async ({
|
163
|
-
collection,
|
164
|
-
doc,
|
165
|
-
operation,
|
166
|
-
req,
|
167
|
-
}) => {
|
168
|
-
if (operation !== 'create') return;
|
169
|
-
|
170
|
-
const locale = req.locale;
|
171
|
-
|
172
|
-
if (!locale || !req.payload.config.localization) return;
|
173
|
-
|
174
|
-
const otherLocales = req.payload.config.localization.locales.filter(
|
175
|
-
(each) => each.code !== locale,
|
176
|
-
);
|
177
|
-
|
178
|
-
const { id } = doc;
|
179
|
-
|
180
|
-
for (const { code } of otherLocales) {
|
181
|
-
await translateOperation({
|
182
|
-
collectionSlug: collection.slug,
|
183
|
-
data: doc,
|
184
|
-
id,
|
185
|
-
locale: code,
|
186
|
-
localeFrom: locale,
|
187
|
-
req,
|
188
|
-
resolver: 'copy',
|
189
|
-
update: true,
|
190
|
-
});
|
191
|
-
}
|
192
|
-
};
|
193
|
-
```
|
1
|
+
# Translator plugin for Payload 3.0 (beta)
|
2
|
+
|
3
|
+
## Install
|
4
|
+
|
5
|
+
`pnpm add @payload-enchants/translator`
|
6
|
+
|
7
|
+
## Video
|
8
|
+
|
9
|
+
https://github.com/r1tsuu/payload-plugin-translator/assets/64744993/d39aeba4-bafc-4c3b-838e-9abc5cf1d64a
|
10
|
+
|
11
|
+
## Features:
|
12
|
+
|
13
|
+
1. A flexible structure with [resolvers](https://github.com/r1tsuu/payload-plugin-translator/tree/6d0c8098467f9b5e757bf9fd8cfe63ff5da68d5b/plugin/src/resolvers) that allows you to apply any kind of transformation to your localizated data.
|
14
|
+
2. Can be used not only from the admin panel, but within Local API as well. [Example of the hook](#example-of-the-hook-that-uses-local-operation-to-copy-the-doc-data-to-other-locales) that automatically fills the other locales data on create
|
15
|
+
3. Out of the box supports 3 resolvers - Copy, Google Translate, OpenAI and your own can be written easily.
|
16
|
+
4. Works with any nested document structure and 2 Rich Text editor adapters - Lexical and Slate.
|
17
|
+
|
18
|
+
## Usage:
|
19
|
+
|
20
|
+
```ts
|
21
|
+
import { buildConfig } from 'payload/config';
|
22
|
+
import { translator } from '@payload-enchants/translator';
|
23
|
+
import { copyResolver } from '@payload-enchants/translator/resolvers/copy';
|
24
|
+
import { googleResolver } from '@payload-enchants/translator/resolvers/google';
|
25
|
+
import { openAIResolver } from '@payload-enchants/translator/resolvers/openAI';
|
26
|
+
|
27
|
+
export default buildConfig({
|
28
|
+
plugins: [
|
29
|
+
translator({
|
30
|
+
// collections with the enabled translator in the admin UI
|
31
|
+
collections: ['posts', 'small-posts'],
|
32
|
+
// globals with the enabled translator in the admin UI
|
33
|
+
globals: [],
|
34
|
+
// add resolvers that you want to include, examples on how to write your own in ./plugin/src/resolvers
|
35
|
+
resolvers: [
|
36
|
+
copyResolver(),
|
37
|
+
googleResolver({
|
38
|
+
apiKey: process.env.GOOGLE_API_KEY!,
|
39
|
+
}),
|
40
|
+
openAIResolver({
|
41
|
+
apiKey: process.env.OPENAI_KEY!,
|
42
|
+
}),
|
43
|
+
],
|
44
|
+
}),
|
45
|
+
],
|
46
|
+
});
|
47
|
+
```
|
48
|
+
|
49
|
+
## Resolvers
|
50
|
+
|
51
|
+
### OpenAI
|
52
|
+
|
53
|
+
#### Config:
|
54
|
+
|
55
|
+
```ts
|
56
|
+
export type OpenAIResolverConfig = {
|
57
|
+
apiKey: string; // API key
|
58
|
+
chunkLength?: number; // How many texts to include into 1 request, default: 100
|
59
|
+
model?: string; // model, default: 'gpt-3.5-turbo'
|
60
|
+
promt?: OpenAIPrompt; // custom prompt
|
61
|
+
};
|
62
|
+
```
|
63
|
+
|
64
|
+
### Custom prompt:
|
65
|
+
|
66
|
+
```ts
|
67
|
+
export type OpenAIPrompt = (args: {
|
68
|
+
localeFrom: string;
|
69
|
+
localeTo: string;
|
70
|
+
texts: string[];
|
71
|
+
}) => string;
|
72
|
+
|
73
|
+
// Default
|
74
|
+
const defaultPromt: OpenAIPrompt = ({ localeFrom, localeTo, texts }) => {
|
75
|
+
return `Translate me the following array: ${JSON.stringify(texts)} in locale=${localeFrom} to locale ${localeTo}, respond me with the same array structure`;
|
76
|
+
};
|
77
|
+
```
|
78
|
+
|
79
|
+
### Google
|
80
|
+
|
81
|
+
#### Config:
|
82
|
+
|
83
|
+
```ts
|
84
|
+
export type GoogleResolverConfig = {
|
85
|
+
apiKey: string; // API key
|
86
|
+
chunkLength?: number; / /How many texts to include into 1 request, default: 100
|
87
|
+
};
|
88
|
+
```
|
89
|
+
|
90
|
+
### Writing your own
|
91
|
+
|
92
|
+
```ts
|
93
|
+
import type { TranslateResolver } from '@payload-enchants/translator/resolvers/types';
|
94
|
+
|
95
|
+
const myResolver: TranslateResolver = {
|
96
|
+
key: 'my',
|
97
|
+
resolve: async (args) => {
|
98
|
+
const { localeFrom, localeTo, req, texts } = args;
|
99
|
+
// here you can apply any kind of transformation to incoming texts, could be as well API call to a service.
|
100
|
+
const transformed = texts.map((each) => `${each} translated to ${localeTo}`);
|
101
|
+
|
102
|
+
return {
|
103
|
+
success: true,
|
104
|
+
translatedTexts: transformed,
|
105
|
+
};
|
106
|
+
},
|
107
|
+
};
|
108
|
+
|
109
|
+
export default buildConfig({
|
110
|
+
plugins: [
|
111
|
+
payloadPluginTranslator({
|
112
|
+
collections: ['posts', 'small-posts'],
|
113
|
+
globals: [],
|
114
|
+
resolvers: [myResolver],
|
115
|
+
}),
|
116
|
+
],
|
117
|
+
// apply translations that will be used for your resolver in the admin UI
|
118
|
+
i18n: {
|
119
|
+
supportedLanguages: { en },
|
120
|
+
translations: {
|
121
|
+
en: {
|
122
|
+
'plugin-translator': {
|
123
|
+
resolver_my_buttonLabel: 'Google Translate',
|
124
|
+
resolver_my_errorMessage: 'An error occurred when trying to translate the data',
|
125
|
+
resolver_my_modalTitle: 'Choose the locale to translate from',
|
126
|
+
resolver_my_submitButtonLabelEmpty: 'Translate only empty fields',
|
127
|
+
resolver_my_submitButtonLabelFull: 'Translate all',
|
128
|
+
resolver_my_successMessage: 'Successfully translated. Press "Save" to apply the changes.',
|
129
|
+
},
|
130
|
+
},
|
131
|
+
},
|
132
|
+
},
|
133
|
+
});
|
134
|
+
```
|
135
|
+
|
136
|
+
## Using the Local API
|
137
|
+
|
138
|
+
```ts
|
139
|
+
import { translateOperation } from '@payload-enchants/translator';
|
140
|
+
|
141
|
+
const translateResult = await translateOperation({
|
142
|
+
collectionSlug: 'posts', // or globalSlug if globals,
|
143
|
+
emptyOnly: false, // optional, should translate all the fields values or only fields that are empty, by default false.
|
144
|
+
id: postDefaultLocale.id, // pass the doc id if it's a collection
|
145
|
+
locale: 'de', // locale to translate to
|
146
|
+
localeFrom: 'en', // locale to translate from
|
147
|
+
payload, // payload instance, you can get it with getPayload or req.payload in hooks
|
148
|
+
req, // PayloadRequest, can be used instead of payload, more appreciable than payload if you have it
|
149
|
+
overrideAccess: false, //
|
150
|
+
resolver: 'copy', // pass resolver key
|
151
|
+
update: true, // optional, should update immediately or just return the translated result, default false
|
152
|
+
data: {}, // Optional, if you want to translate from your data passed here instead of the current doc, should be in "localeFrom" locale, for example { title: "Hello" }
|
153
|
+
});
|
154
|
+
```
|
155
|
+
|
156
|
+
### Example of the hook that uses local operation to copy the doc data to other locales
|
157
|
+
|
158
|
+
```ts
|
159
|
+
import type { CollectionAfterChangeHook } from 'payload/types';
|
160
|
+
import { translateOperation } from '@payload-enchants/translator';
|
161
|
+
|
162
|
+
export const copyOtherLocales: CollectionAfterChangeHook = async ({
|
163
|
+
collection,
|
164
|
+
doc,
|
165
|
+
operation,
|
166
|
+
req,
|
167
|
+
}) => {
|
168
|
+
if (operation !== 'create') return;
|
169
|
+
|
170
|
+
const locale = req.locale;
|
171
|
+
|
172
|
+
if (!locale || !req.payload.config.localization) return;
|
173
|
+
|
174
|
+
const otherLocales = req.payload.config.localization.locales.filter(
|
175
|
+
(each) => each.code !== locale,
|
176
|
+
);
|
177
|
+
|
178
|
+
const { id } = doc;
|
179
|
+
|
180
|
+
for (const { code } of otherLocales) {
|
181
|
+
await translateOperation({
|
182
|
+
collectionSlug: collection.slug,
|
183
|
+
data: doc,
|
184
|
+
id,
|
185
|
+
locale: code,
|
186
|
+
localeFrom: locale,
|
187
|
+
req,
|
188
|
+
resolver: 'copy',
|
189
|
+
update: true,
|
190
|
+
});
|
191
|
+
}
|
192
|
+
};
|
193
|
+
```
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../../src/client/api/index.ts"],"sourcesContent":["import type { TranslateEndpointArgs, TranslateResult } from '../../translate/types';\
|
1
|
+
{"version":3,"sources":["../../../src/client/api/index.ts"],"sourcesContent":["import type { TranslateEndpointArgs, TranslateResult } from '../../translate/types';\n\nexport const createClient = ({ api, serverURL }: { api: string; serverURL: string }) => {\n const translate = async (args: TranslateEndpointArgs): Promise<TranslateResult> => {\n try {\n const response = await fetch(`${serverURL}${api}/translator/translate`, {\n body: JSON.stringify(args),\n credentials: 'include',\n headers: {\n 'Content-Type': 'application/json',\n },\n method: 'POST',\n });\n\n if (!response.ok) return { success: false };\n\n return response.json();\n } catch (e) {\n if (e instanceof Error) console.error(e.message);\n\n return { success: false };\n }\n };\n\n return {\n translate,\n };\n};\n"],"names":["createClient","api","serverURL","translate","args","response","fetch","body","JSON","stringify","credentials","headers","method","ok","success","json","e","Error","console","error","message"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAEA,OAAO,MAAMA,eAAe,CAAC,EAAEC,GAAG,EAAEC,SAAS,EAAsC;IACjF,MAAMC,YAAY,OAAOC;QACvB,IAAI;YACF,MAAMC,WAAW,MAAMC,MAAM,CAAC,EAAEJ,UAAU,EAAED,IAAI,qBAAqB,CAAC,EAAE;gBACtEM,MAAMC,KAAKC,SAAS,CAACL;gBACrBM,aAAa;gBACbC,SAAS;oBACP,gBAAgB;gBAClB;gBACAC,QAAQ;YACV;YAEA,IAAI,CAACP,SAASQ,EAAE,EAAE,OAAO;gBAAEC,SAAS;YAAM;YAE1C,OAAOT,SAASU,IAAI;QACtB,EAAE,OAAOC,GAAG;YACV,IAAIA,aAAaC,OAAOC,QAAQC,KAAK,CAACH,EAAEI,OAAO;YAE/C,OAAO;gBAAEN,SAAS;YAAM;QAC1B;IACF;IAEA,OAAO;QACLX;IACF;AACF,EAAE"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../../../src/client/components/CustomSaveButton/CustomSaveButton.tsx"],"sourcesContent":["'use client';\
|
1
|
+
{"version":3,"sources":["../../../../src/client/components/CustomSaveButton/CustomSaveButton.tsx"],"sourcesContent":["'use client';\n\nimport './styles.scss';\n\nimport { DefaultSaveButton } from '@payloadcms/ui/elements/Save';\nimport { useConfig } from '@payloadcms/ui/providers/Config';\nimport { useDocumentInfo } from '@payloadcms/ui/providers/DocumentInfo';\n\nimport type { TranslateResolver } from '../../../resolvers/types';\nimport { TranslatorProvider } from '../../providers/Translator/TranslatorProvider';\nimport { ResolverButton } from '../ResolverButton';\nimport { TranslatorModal } from '../TranslatorModal';\n\nexport const CustomSaveButton = () => {\n const config = useConfig();\n\n const { globalSlug, id } = useDocumentInfo();\n\n const resolvers = (config.admin?.custom?.translator?.resolvers as TranslateResolver[]) ?? [];\n\n if (!id && !globalSlug) return <DefaultSaveButton />;\n\n return (\n <TranslatorProvider>\n <div className={'translator__custom-save-button'}>\n <TranslatorModal />\n {resolvers.map((resolver) => (\n <ResolverButton key={resolver.key} resolver={resolver} />\n ))}\n <DefaultSaveButton />\n </div>\n </TranslatorProvider>\n );\n};\n"],"names":["DefaultSaveButton","useConfig","useDocumentInfo","TranslatorProvider","ResolverButton","TranslatorModal","CustomSaveButton","config","globalSlug","id","resolvers","admin","custom","translator","div","className","map","resolver","key"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAAA;;AAEA,OAAO,gBAAgB;AAEvB,SAASA,iBAAiB,QAAQ,+BAA+B;AACjE,SAASC,SAAS,QAAQ,kCAAkC;AAC5D,SAASC,eAAe,QAAQ,wCAAwC;AAGxE,SAASC,kBAAkB,QAAQ,gDAAgD;AACnF,SAASC,cAAc,QAAQ,oBAAoB;AACnD,SAASC,eAAe,QAAQ,qBAAqB;AAErD,OAAO,MAAMC,mBAAmB;IAC9B,MAAMC,SAASN;IAEf,MAAM,EAAEO,UAAU,EAAEC,EAAE,EAAE,GAAGP;IAE3B,MAAMQ,YAAY,AAACH,OAAOI,KAAK,EAAEC,QAAQC,YAAYH,aAAqC,EAAE;IAE5F,IAAI,CAACD,MAAM,CAACD,YAAY,qBAAO,KAACR;IAEhC,qBACE,KAACG;kBACC,cAAA,MAACW;YAAIC,WAAW;;8BACd,KAACV;gBACAK,UAAUM,GAAG,CAAC,CAACC,yBACd,KAACb;wBAAkCa,UAAUA;uBAAxBA,SAASC,GAAG;8BAEnC,KAAClB;;;;AAIT,EAAE"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../../../src/client/components/CustomSaveButton/index.ts"],"sourcesContent":["export * from './CustomSaveButton';\
|
1
|
+
{"version":3,"sources":["../../../../src/client/components/CustomSaveButton/index.ts"],"sourcesContent":["export * from './CustomSaveButton';\n"],"names":[],"rangeMappings":"","mappings":"AAAA,cAAc,qBAAqB"}
|
@@ -1,5 +1,5 @@
|
|
1
|
-
.translator__custom-save-button {
|
2
|
-
display: flex;
|
3
|
-
align-items: center;
|
4
|
-
gap: 10px;
|
5
|
-
}
|
1
|
+
.translator__custom-save-button {
|
2
|
+
display: flex;
|
3
|
+
align-items: center;
|
4
|
+
gap: 10px;
|
5
|
+
}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../../../src/client/components/LocaleLabel/LocaleLabel.tsx"],"sourcesContent":["import { getTranslation } from '@payloadcms/translations';\
|
1
|
+
{"version":3,"sources":["../../../../src/client/components/LocaleLabel/LocaleLabel.tsx"],"sourcesContent":["import { getTranslation } from '@payloadcms/translations';\nimport { Chevron } from '@payloadcms/ui/icons/Chevron';\nimport { useTranslation } from '@payloadcms/ui/providers/Translation';\nimport type { Locale } from 'payload/config';\n\nconst baseClass = 'localizer-button';\n\nexport const LocaleLabel = ({ locale }: { locale: Locale }) => {\n const { i18n, t } = useTranslation();\n\n return (\n <div aria-label={t('general:locale')} className={baseClass}>\n <div className={`${baseClass}__label`}>{`${t('general:locale')}:`}</div>\n \n <span className={`${baseClass}__current-label`}>\n {`${getTranslation(locale.label, i18n)}`}\n </span>\n \n <Chevron className={`${baseClass}__chevron`} />\n </div>\n );\n};\n"],"names":["getTranslation","Chevron","useTranslation","baseClass","LocaleLabel","locale","i18n","t","div","aria-label","className","span","label"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":";AAAA,SAASA,cAAc,QAAQ,2BAA2B;AAC1D,SAASC,OAAO,QAAQ,+BAA+B;AACvD,SAASC,cAAc,QAAQ,uCAAuC;AAGtE,MAAMC,YAAY;AAElB,OAAO,MAAMC,cAAc,CAAC,EAAEC,MAAM,EAAsB;IACxD,MAAM,EAAEC,IAAI,EAAEC,CAAC,EAAE,GAAGL;IAEpB,qBACE,MAACM;QAAIC,cAAYF,EAAE;QAAmBG,WAAWP;;0BAC/C,KAACK;gBAAIE,WAAW,CAAC,EAAEP,UAAU,OAAO,CAAC;0BAAG,CAAC,EAAEI,EAAE,kBAAkB,CAAC,CAAC;;YAAO;0BAExE,KAACI;gBAAKD,WAAW,CAAC,EAAEP,UAAU,eAAe,CAAC;0BAC3C,CAAC,EAAEH,eAAeK,OAAOO,KAAK,EAAEN,MAAM,CAAC;;YACnC;0BAEP,KAACL;gBAAQS,WAAW,CAAC,EAAEP,UAAU,SAAS,CAAC;;;;AAGjD,EAAE"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../../../src/client/components/LocaleLabel/index.ts"],"sourcesContent":["export * from './LocaleLabel';\
|
1
|
+
{"version":3,"sources":["../../../../src/client/components/LocaleLabel/index.ts"],"sourcesContent":["export * from './LocaleLabel';\n"],"names":[],"rangeMappings":"","mappings":"AAAA,cAAc,gBAAgB"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../../../src/client/components/ResolverButton/ResolverButton.tsx"],"sourcesContent":["import { Button } from '@payloadcms/ui/elements';\
|
1
|
+
{"version":3,"sources":["../../../../src/client/components/ResolverButton/ResolverButton.tsx"],"sourcesContent":["import { Button } from '@payloadcms/ui/elements';\nimport { useTranslation } from '@payloadcms/ui/providers/Translation';\n\nimport type { TranslateResolver } from '../../../resolvers/types';\nimport { useTranslator } from '../../providers/Translator/context';\n\nexport const ResolverButton = ({\n resolver: { key: resolverKey },\n}: {\n resolver: TranslateResolver;\n}) => {\n const { openTranslator } = useTranslator();\n\n const { t } = useTranslation();\n\n const handleClick = () => openTranslator({ resolverKey });\n\n return (\n <Button onClick={handleClick} size='small'>\n {t(`plugin-translator:resolver_${resolverKey}_buttonLabel`)}\n </Button>\n );\n};\n"],"names":["Button","useTranslation","useTranslator","ResolverButton","resolver","key","resolverKey","openTranslator","t","handleClick","onClick","size"],"rangeMappings":";;;;;;;;;;;;;;;","mappings":";AAAA,SAASA,MAAM,QAAQ,0BAA0B;AACjD,SAASC,cAAc,QAAQ,uCAAuC;AAGtE,SAASC,aAAa,QAAQ,qCAAqC;AAEnE,OAAO,MAAMC,iBAAiB,CAAC,EAC7BC,UAAU,EAAEC,KAAKC,WAAW,EAAE,EAG/B;IACC,MAAM,EAAEC,cAAc,EAAE,GAAGL;IAE3B,MAAM,EAAEM,CAAC,EAAE,GAAGP;IAEd,MAAMQ,cAAc,IAAMF,eAAe;YAAED;QAAY;IAEvD,qBACE,KAACN;QAAOU,SAASD;QAAaE,MAAK;kBAChCH,EAAE,CAAC,2BAA2B,EAAEF,YAAY,YAAY,CAAC;;AAGhE,EAAE"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../../../src/client/components/ResolverButton/index.ts"],"sourcesContent":["export * from './ResolverButton';\
|
1
|
+
{"version":3,"sources":["../../../../src/client/components/ResolverButton/index.ts"],"sourcesContent":["export * from './ResolverButton';\n"],"names":[],"rangeMappings":"","mappings":"AAAA,cAAc,mBAAmB"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../../../src/client/components/TranslatorModal/Content.tsx"],"sourcesContent":["import { getTranslation } from '@payloadcms/translations';\
|
1
|
+
{"version":3,"sources":["../../../../src/client/components/TranslatorModal/Content.tsx"],"sourcesContent":["import { getTranslation } from '@payloadcms/translations';\nimport { Button, Popup, PopupList } from '@payloadcms/ui/elements';\nimport { useTranslation } from '@payloadcms/ui/providers/Translation';\n\nimport { useTranslator } from '../../providers/Translator/context';\nimport { LocaleLabel } from '../LocaleLabel';\n\nexport const Content = () => {\n const {\n localeToTranslateFrom: localeCodeToTranslateFrom,\n localesOptions,\n resolverT,\n setLocaleToTranslateFrom,\n submit,\n } = useTranslator();\n\n const { i18n } = useTranslation();\n\n const localeToTranslateFrom = localesOptions.find(\n (each) => each.code === localeCodeToTranslateFrom,\n );\n\n return (\n <div className={'translator__content'}>\n <h2>{resolverT('modalTitle')}</h2>\n {localeToTranslateFrom && (\n <Popup\n button={<LocaleLabel locale={localeToTranslateFrom} />}\n horizontalAlign='center'\n render={({ close }) => (\n <PopupList.ButtonGroup>\n {localesOptions.map((option) => {\n const label = getTranslation(option.label, i18n);\n\n return (\n <PopupList.Button\n active={option.code === localeCodeToTranslateFrom}\n key={option.code}\n onClick={() => {\n setLocaleToTranslateFrom(option.code);\n close();\n }}\n >\n {label}\n {label !== option.code && ` (${option.code})`}\n </PopupList.Button>\n );\n })}\n </PopupList.ButtonGroup>\n )}\n verticalAlign='bottom'\n />\n )}\n <div className={'translator__buttons'}>\n <Button onClick={() => submit({ emptyOnly: false })}>\n {resolverT('submitButtonLabelFull')}\n </Button>\n <Button onClick={() => submit({ emptyOnly: true })}>\n {resolverT('submitButtonLabelEmpty')}\n </Button>\n </div>\n </div>\n );\n};\n"],"names":["getTranslation","Button","Popup","PopupList","useTranslation","useTranslator","LocaleLabel","Content","localeToTranslateFrom","localeCodeToTranslateFrom","localesOptions","resolverT","setLocaleToTranslateFrom","submit","i18n","find","each","code","div","className","h2","button","locale","horizontalAlign","render","close","ButtonGroup","map","option","label","active","onClick","verticalAlign","emptyOnly"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":";AAAA,SAASA,cAAc,QAAQ,2BAA2B;AAC1D,SAASC,MAAM,EAAEC,KAAK,EAAEC,SAAS,QAAQ,0BAA0B;AACnE,SAASC,cAAc,QAAQ,uCAAuC;AAEtE,SAASC,aAAa,QAAQ,qCAAqC;AACnE,SAASC,WAAW,QAAQ,iBAAiB;AAE7C,OAAO,MAAMC,UAAU;IACrB,MAAM,EACJC,uBAAuBC,yBAAyB,EAChDC,cAAc,EACdC,SAAS,EACTC,wBAAwB,EACxBC,MAAM,EACP,GAAGR;IAEJ,MAAM,EAAES,IAAI,EAAE,GAAGV;IAEjB,MAAMI,wBAAwBE,eAAeK,IAAI,CAC/C,CAACC,OAASA,KAAKC,IAAI,KAAKR;IAG1B,qBACE,MAACS;QAAIC,WAAW;;0BACd,KAACC;0BAAIT,UAAU;;YACdH,uCACC,KAACN;gBACCmB,sBAAQ,KAACf;oBAAYgB,QAAQd;;gBAC7Be,iBAAgB;gBAChBC,QAAQ,CAAC,EAAEC,KAAK,EAAE,iBAChB,KAACtB,UAAUuB,WAAW;kCACnBhB,eAAeiB,GAAG,CAAC,CAACC;4BACnB,MAAMC,QAAQ7B,eAAe4B,OAAOC,KAAK,EAAEf;4BAE3C,qBACE,MAACX,UAAUF,MAAM;gCACf6B,QAAQF,OAAOX,IAAI,KAAKR;gCAExBsB,SAAS;oCACPnB,yBAAyBgB,OAAOX,IAAI;oCACpCQ;gCACF;;oCAECI;oCACAA,UAAUD,OAAOX,IAAI,IAAI,CAAC,EAAE,EAAEW,OAAOX,IAAI,CAAC,CAAC,CAAC;;+BAPxCW,OAAOX,IAAI;wBAUtB;;gBAGJe,eAAc;;0BAGlB,MAACd;gBAAIC,WAAW;;kCACd,KAAClB;wBAAO8B,SAAS,IAAMlB,OAAO;gCAAEoB,WAAW;4BAAM;kCAC9CtB,UAAU;;kCAEb,KAACV;wBAAO8B,SAAS,IAAMlB,OAAO;gCAAEoB,WAAW;4BAAK;kCAC7CtB,UAAU;;;;;;AAKrB,EAAE"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../../../src/client/components/TranslatorModal/TranslatorModal.tsx"],"sourcesContent":["import './styles.scss';\
|
1
|
+
{"version":3,"sources":["../../../../src/client/components/TranslatorModal/TranslatorModal.tsx"],"sourcesContent":["import './styles.scss';\n\nimport { Modal } from '@payloadcms/ui/elements';\n\nimport { useTranslator } from '../../providers/Translator/context';\nimport { Content } from './Content';\n\nexport const TranslatorModal = () => {\n const { closeTranslator, modalSlug, resolver } = useTranslator();\n\n if (!resolver) return;\n\n return (\n <Modal className={'translator__modal'} slug={modalSlug}>\n <div className={'translator__wrapper'}>\n <span\n aria-label='Close'\n className={'translator__close'}\n onClick={closeTranslator}\n role='button'\n />\n <Content />\n </div>\n </Modal>\n );\n};\n"],"names":["Modal","useTranslator","Content","TranslatorModal","closeTranslator","modalSlug","resolver","className","slug","div","span","aria-label","onClick","role"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;","mappings":";AAAA,OAAO,gBAAgB;AAEvB,SAASA,KAAK,QAAQ,0BAA0B;AAEhD,SAASC,aAAa,QAAQ,qCAAqC;AACnE,SAASC,OAAO,QAAQ,YAAY;AAEpC,OAAO,MAAMC,kBAAkB;IAC7B,MAAM,EAAEC,eAAe,EAAEC,SAAS,EAAEC,QAAQ,EAAE,GAAGL;IAEjD,IAAI,CAACK,UAAU;IAEf,qBACE,KAACN;QAAMO,WAAW;QAAqBC,MAAMH;kBAC3C,cAAA,MAACI;YAAIF,WAAW;;8BACd,KAACG;oBACCC,cAAW;oBACXJ,WAAW;oBACXK,SAASR;oBACTS,MAAK;;8BAEP,KAACX;;;;AAIT,EAAE"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../../../src/client/components/TranslatorModal/index.ts"],"sourcesContent":["export * from './TranslatorModal';\
|
1
|
+
{"version":3,"sources":["../../../../src/client/components/TranslatorModal/index.ts"],"sourcesContent":["export * from './TranslatorModal';\n"],"names":[],"rangeMappings":"","mappings":"AAAA,cAAc,oBAAoB"}
|
@@ -1,76 +1,76 @@
|
|
1
|
-
.translator {
|
2
|
-
&__modal {
|
3
|
-
display: flex;
|
4
|
-
position: relative;
|
5
|
-
justify-content: center;
|
6
|
-
align-items: center;
|
7
|
-
width: fit-content;
|
8
|
-
height: fit-content;
|
9
|
-
}
|
10
|
-
|
11
|
-
&__wrapper {
|
12
|
-
display: flex;
|
13
|
-
position: relative;
|
14
|
-
flex-direction: column;
|
15
|
-
gap: var(--base);
|
16
|
-
z-index: 1;
|
17
|
-
background: var(--theme-elevation-50);
|
18
|
-
padding: 50px;
|
19
|
-
}
|
20
|
-
|
21
|
-
&__content {
|
22
|
-
display: flex;
|
23
|
-
flex-direction: column;
|
24
|
-
align-items: center;
|
25
|
-
gap: var(--base);
|
26
|
-
max-width: 400px;
|
27
|
-
|
28
|
-
h2 {
|
29
|
-
margin: 0;
|
30
|
-
text-align: center;
|
31
|
-
}
|
32
|
-
}
|
33
|
-
|
34
|
-
&__buttons {
|
35
|
-
display: flex;
|
36
|
-
justify-content: center;
|
37
|
-
gap: 10px;
|
38
|
-
width: 100%;
|
39
|
-
|
40
|
-
button {
|
41
|
-
margin: 0;
|
42
|
-
}
|
43
|
-
}
|
44
|
-
|
45
|
-
&__close {
|
46
|
-
position: absolute;
|
47
|
-
top: 10px;
|
48
|
-
right: 10px;
|
49
|
-
transition: 0.25s;
|
50
|
-
cursor: pointer;
|
51
|
-
width: 32px;
|
52
|
-
height: 32px;
|
53
|
-
|
54
|
-
&:hover {
|
55
|
-
opacity: 0.6;
|
56
|
-
}
|
57
|
-
|
58
|
-
&:before,
|
59
|
-
&:after {
|
60
|
-
position: absolute;
|
61
|
-
left: 15px;
|
62
|
-
background-color: var(--theme-elevation-800);
|
63
|
-
width: 2px;
|
64
|
-
height: 33px;
|
65
|
-
content: ' ';
|
66
|
-
}
|
67
|
-
|
68
|
-
&:before {
|
69
|
-
transform: rotate(45deg);
|
70
|
-
}
|
71
|
-
|
72
|
-
&:after {
|
73
|
-
transform: rotate(-45deg);
|
74
|
-
}
|
75
|
-
}
|
76
|
-
}
|
1
|
+
.translator {
|
2
|
+
&__modal {
|
3
|
+
display: flex;
|
4
|
+
position: relative;
|
5
|
+
justify-content: center;
|
6
|
+
align-items: center;
|
7
|
+
width: fit-content;
|
8
|
+
height: fit-content;
|
9
|
+
}
|
10
|
+
|
11
|
+
&__wrapper {
|
12
|
+
display: flex;
|
13
|
+
position: relative;
|
14
|
+
flex-direction: column;
|
15
|
+
gap: var(--base);
|
16
|
+
z-index: 1;
|
17
|
+
background: var(--theme-elevation-50);
|
18
|
+
padding: 50px;
|
19
|
+
}
|
20
|
+
|
21
|
+
&__content {
|
22
|
+
display: flex;
|
23
|
+
flex-direction: column;
|
24
|
+
align-items: center;
|
25
|
+
gap: var(--base);
|
26
|
+
max-width: 400px;
|
27
|
+
|
28
|
+
h2 {
|
29
|
+
margin: 0;
|
30
|
+
text-align: center;
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
&__buttons {
|
35
|
+
display: flex;
|
36
|
+
justify-content: center;
|
37
|
+
gap: 10px;
|
38
|
+
width: 100%;
|
39
|
+
|
40
|
+
button {
|
41
|
+
margin: 0;
|
42
|
+
}
|
43
|
+
}
|
44
|
+
|
45
|
+
&__close {
|
46
|
+
position: absolute;
|
47
|
+
top: 10px;
|
48
|
+
right: 10px;
|
49
|
+
transition: 0.25s;
|
50
|
+
cursor: pointer;
|
51
|
+
width: 32px;
|
52
|
+
height: 32px;
|
53
|
+
|
54
|
+
&:hover {
|
55
|
+
opacity: 0.6;
|
56
|
+
}
|
57
|
+
|
58
|
+
&:before,
|
59
|
+
&:after {
|
60
|
+
position: absolute;
|
61
|
+
left: 15px;
|
62
|
+
background-color: var(--theme-elevation-800);
|
63
|
+
width: 2px;
|
64
|
+
height: 33px;
|
65
|
+
content: ' ';
|
66
|
+
}
|
67
|
+
|
68
|
+
&:before {
|
69
|
+
transform: rotate(45deg);
|
70
|
+
}
|
71
|
+
|
72
|
+
&:after {
|
73
|
+
transform: rotate(-45deg);
|
74
|
+
}
|
75
|
+
}
|
76
|
+
}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../../../src/client/providers/Translator/TranslatorProvider.tsx"],"sourcesContent":["import { toast } from '@payloadcms/ui/elements';\
|
1
|
+
{"version":3,"sources":["../../../../src/client/providers/Translator/TranslatorProvider.tsx"],"sourcesContent":["import { toast } from '@payloadcms/ui/elements';\nimport { useModal } from '@payloadcms/ui/elements/Modal';\nimport { useAllFormFields } from '@payloadcms/ui/forms/Form';\nimport { useConfig } from '@payloadcms/ui/providers/Config';\nimport { useDocumentInfo } from '@payloadcms/ui/providers/DocumentInfo';\nimport { useLocale } from '@payloadcms/ui/providers/Locale';\nimport { useTranslation } from '@payloadcms/ui/providers/Translation';\nimport { getFormState } from '@payloadcms/ui/utilities/getFormState';\nimport { reduceFieldsToValues } from '@payloadcms/ui/utilities/reduceFieldsToValues';\nimport { type ReactNode, useMemo, useState } from 'react';\n\nimport type { TranslateResolver } from '../../../resolvers/types';\nimport type { TranslateArgs } from '../../../translate/types';\nimport { createClient } from '../../api';\nimport { TranslatorContext } from './context';\n\nconst modalSlug = 'translator-modal';\n\nexport const TranslatorProvider = ({ children }: { children: ReactNode }) => {\n const [resolver, setResolver] = useState<null | string>(null);\n\n const [data, dispatch] = useAllFormFields();\n\n const { collectionSlug, globalSlug, id } = useDocumentInfo();\n\n const modal = useModal();\n\n const { t } = useTranslation();\n\n const resolverT = (\n key:\n | 'buttonLabel'\n | 'errorMessage'\n | 'modalTitle'\n | 'submitButtonLabelEmpty'\n | 'submitButtonLabelFull'\n | 'successMessage',\n ) => {\n if (!resolver) return '';\n\n return t(`plugin-translator:resolver_${resolver}_${key}`);\n };\n\n const locale = useLocale();\n\n const {\n admin: { custom },\n localization,\n routes: { api },\n serverURL,\n } = useConfig();\n\n const apiClient = createClient({ api, serverURL });\n\n const resolverConfig = useMemo(() => {\n if (!resolver) return null;\n\n const resolvers = (custom?.translator?.resolvers as TranslateResolver[]) || undefined;\n\n if (!resolvers) return null;\n\n const resolverConfig = resolvers.find((each) => each.key === resolver);\n\n return resolverConfig ?? null;\n }, [custom, resolver]);\n\n if (!localization)\n throw new Error('Localization config is not provided and PluginTranslator is used');\n\n const localesOptions = localization.locales.filter((each) => each.code !== locale.code);\n\n const [localeToTranslateFrom, setLocaleToTranslateFrom] = useState(() => {\n const defaultFromOptions = localesOptions.find(\n (each) => localization.defaultLocale === each.code,\n );\n\n if (defaultFromOptions) return defaultFromOptions.code;\n\n return localesOptions[0].code;\n });\n\n const closeTranslator = () => modal.closeModal(modalSlug);\n\n const submit = async ({ emptyOnly }: { emptyOnly: boolean }) => {\n if (!resolver) return;\n\n const args: TranslateArgs = {\n collectionSlug,\n data: reduceFieldsToValues(data, true),\n emptyOnly,\n globalSlug,\n id: id === null ? undefined : id,\n locale: locale.code,\n localeFrom: localeToTranslateFrom,\n resolver,\n };\n\n const result = await apiClient.translate(args);\n\n if (!result.success) {\n toast.error(resolverT('errorMessage'));\n\n return;\n }\n\n dispatch({\n state: await getFormState({\n apiRoute: api,\n body: {\n collectionSlug,\n data: result.translatedData,\n globalSlug,\n locale: locale.code,\n schemaPath: collectionSlug || globalSlug || '',\n },\n serverURL,\n }),\n type: 'REPLACE_STATE',\n });\n\n if (resolverConfig) toast.success(resolverT('successMessage'));\n closeTranslator();\n };\n\n return (\n <TranslatorContext.Provider\n value={{\n closeTranslator,\n localeToTranslateFrom,\n localesOptions,\n modalSlug,\n openTranslator: ({ resolverKey }) => {\n setResolver(resolverKey);\n modal.openModal(modalSlug);\n },\n resolver: resolverConfig,\n resolverT,\n setLocaleToTranslateFrom,\n submit,\n }}\n >\n {children}\n </TranslatorContext.Provider>\n );\n};\n"],"names":["toast","useModal","useAllFormFields","useConfig","useDocumentInfo","useLocale","useTranslation","getFormState","reduceFieldsToValues","useMemo","useState","createClient","TranslatorContext","modalSlug","TranslatorProvider","children","resolver","setResolver","data","dispatch","collectionSlug","globalSlug","id","modal","t","resolverT","key","locale","admin","custom","localization","routes","api","serverURL","apiClient","resolverConfig","resolvers","translator","undefined","find","each","Error","localesOptions","locales","filter","code","localeToTranslateFrom","setLocaleToTranslateFrom","defaultFromOptions","defaultLocale","closeTranslator","closeModal","submit","emptyOnly","args","localeFrom","result","translate","success","error","state","apiRoute","body","translatedData","schemaPath","type","Provider","value","openTranslator","resolverKey","openModal"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../../../src/client/providers/Translator/context.ts"],"sourcesContent":["import type { Locale } from 'payload/config';\
|
1
|
+
{"version":3,"sources":["../../../../src/client/providers/Translator/context.ts"],"sourcesContent":["import type { Locale } from 'payload/config';\nimport { createContext, useContext } from 'react';\n\nimport type { TranslateResolver } from '../../../resolvers/types';\n\ntype TranslatorContextData = {\n closeTranslator: () => void;\n localeToTranslateFrom: string;\n localesOptions: Locale[];\n modalSlug: string;\n openTranslator: (args: { resolverKey: string }) => void;\n resolver: TranslateResolver | null;\n resolverT: (\n key:\n | 'buttonLabel'\n | 'errorMessage'\n | 'modalTitle'\n | 'submitButtonLabelEmpty'\n | 'submitButtonLabelFull'\n | 'successMessage',\n ) => string;\n setLocaleToTranslateFrom: (code: string) => void;\n submit: (args: { emptyOnly: boolean }) => Promise<void>;\n};\n\nexport const TranslatorContext = createContext<TranslatorContextData | null>(null);\n\nexport const useTranslator = () => {\n const context = useContext(TranslatorContext);\n\n if (context === null) throw new Error('useTranslator must be used within TranslatorProvider');\n\n return context;\n};\n"],"names":["createContext","useContext","TranslatorContext","useTranslator","context","Error"],"rangeMappings":";;;;;;","mappings":"AACA,SAASA,aAAa,EAAEC,UAAU,QAAQ,QAAQ;AAwBlD,OAAO,MAAMC,oBAAoBF,cAA4C,MAAM;AAEnF,OAAO,MAAMG,gBAAgB;IAC3B,MAAMC,UAAUH,WAAWC;IAE3B,IAAIE,YAAY,MAAM,MAAM,IAAIC,MAAM;IAEtC,OAAOD;AACT,EAAE"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../src/i18n-translations.ts"],"sourcesContent":["export const translations = {\
|
1
|
+
{"version":3,"sources":["../src/i18n-translations.ts"],"sourcesContent":["export const translations = {\n en: {\n 'plugin-translator': {\n resolver_copy_buttonLabel: 'Copy from other locale',\n resolver_copy_errorMessage: 'An error occurred when trying to translate the data',\n resolver_copy_modalTitle: 'Choose the locale to copy from',\n resolver_copy_submitButtonLabelEmpty: 'Copy only empty fields',\n resolver_copy_submitButtonLabelFull: 'Copy all',\n resolver_copy_successMessage: 'Successfully copied. Press \"Save\" to apply the changes.',\n\n resolver_google_buttonLabel: 'Google Translate',\n resolver_google_errorMessage: 'An error occurred when trying to translate the data',\n resolver_google_modalTitle: 'Choose the locale to translate from',\n resolver_google_submitButtonLabelEmpty: 'Translate only empty fields',\n resolver_google_submitButtonLabelFull: 'Translate all',\n resolver_google_successMessage: 'Successfully translated. Press \"Save\" to apply the changes.',\n\n resolver_openai_buttonLabel: 'AI Translate',\n resolver_openai_errorMessage: 'An error occurred when trying to translate the data',\n resolver_openai_modalTitle: 'Choose the locale to translate from',\n resolver_openai_submitButtonLabelEmpty: 'Translate only empty fields',\n resolver_openai_submitButtonLabelFull: 'Translate all',\n resolver_openai_successMessage: 'Successfully translated. Press \"Save\" to apply the changes.',\n },\n },\n};\n"],"names":["translations","en","resolver_copy_buttonLabel","resolver_copy_errorMessage","resolver_copy_modalTitle","resolver_copy_submitButtonLabelEmpty","resolver_copy_submitButtonLabelFull","resolver_copy_successMessage","resolver_google_buttonLabel","resolver_google_errorMessage","resolver_google_modalTitle","resolver_google_submitButtonLabelEmpty","resolver_google_submitButtonLabelFull","resolver_google_successMessage","resolver_openai_buttonLabel","resolver_openai_errorMessage","resolver_openai_modalTitle","resolver_openai_submitButtonLabelEmpty","resolver_openai_submitButtonLabelFull","resolver_openai_successMessage"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAAA,OAAO,MAAMA,eAAe;IAC1BC,IAAI;QACF,qBAAqB;YACnBC,2BAA2B;YAC3BC,4BAA4B;YAC5BC,0BAA0B;YAC1BC,sCAAsC;YACtCC,qCAAqC;YACrCC,8BAA8B;YAE9BC,6BAA6B;YAC7BC,8BAA8B;YAC9BC,4BAA4B;YAC5BC,wCAAwC;YACxCC,uCAAuC;YACvCC,gCAAgC;YAEhCC,6BAA6B;YAC7BC,8BAA8B;YAC9BC,4BAA4B;YAC5BC,wCAAwC;YACxCC,uCAAuC;YACvCC,gCAAgC;QAClC;IACF;AACF,EAAE"}
|
package/dist/index.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/* eslint-disable perfectionist/sort-named-exports */\
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/* eslint-disable perfectionist/sort-named-exports */\nimport type { Plugin } from 'payload/config';\nimport { deepMerge } from 'payload/utilities';\n\nimport { CustomSaveButton } from './client/components/CustomSaveButton';\nimport { translations } from './i18n-translations';\nimport { translateEndpoint } from './translate/endpoint';\nimport { translateOperation } from './translate/operation';\nimport type { TranslatorConfig } from './types';\n\nexport { translateOperation };\n\nexport const translator: (pluginConfig: TranslatorConfig) => Plugin = (pluginConfig) => {\n return (config) => {\n if (pluginConfig.disabled || !config.localization || config.localization.locales.length < 2)\n return config;\n\n return {\n ...config,\n admin: {\n ...(config.admin ?? {}),\n custom: {\n ...(config.admin?.custom ?? {}),\n translator: {\n resolvers: pluginConfig.resolvers.map(({ key }) => ({ key })),\n },\n },\n },\n collections:\n config.collections?.map((collection) => {\n if (!pluginConfig.collections.includes(collection.slug)) return collection;\n\n return {\n ...collection,\n admin: {\n ...(collection.admin ?? {}),\n components: {\n ...(collection.admin?.components ?? {}),\n edit: {\n ...(collection.admin?.components?.edit ?? {}),\n SaveButton: CustomSaveButton,\n },\n },\n },\n };\n }) ?? [],\n custom: {\n ...(config.custom ?? {}),\n translator: {\n resolvers: pluginConfig.resolvers,\n },\n },\n endpoints: [\n ...(config.endpoints ?? []),\n {\n handler: translateEndpoint,\n method: 'post',\n path: '/translator/translate',\n },\n ],\n globals:\n config.globals?.map((global) => {\n if (!pluginConfig.globals.includes(global.slug)) return global;\n\n return {\n ...global,\n admin: {\n ...(global.admin ?? {}),\n components: {\n ...(global.admin?.components ?? {}),\n elements: {\n ...(global.admin?.components?.elements ?? {}),\n SaveButton: CustomSaveButton,\n },\n },\n },\n };\n }) ?? [],\n i18n: {\n ...config.i18n,\n translations: {\n ...deepMerge(config.i18n?.translations ?? {}, translations),\n },\n },\n };\n };\n};\n"],"names":["deepMerge","CustomSaveButton","translations","translateEndpoint","translateOperation","translator","pluginConfig","config","disabled","localization","locales","length","admin","custom","resolvers","map","key","collections","collection","includes","slug","components","edit","SaveButton","endpoints","handler","method","path","globals","global","elements","i18n"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAAA,mDAAmD,GAEnD,SAASA,SAAS,QAAQ,oBAAoB;AAE9C,SAASC,gBAAgB,QAAQ,uCAAuC;AACxE,SAASC,YAAY,QAAQ,sBAAsB;AACnD,SAASC,iBAAiB,QAAQ,uBAAuB;AACzD,SAASC,kBAAkB,QAAQ,wBAAwB;AAG3D,SAASA,kBAAkB,GAAG;AAE9B,OAAO,MAAMC,aAAyD,CAACC;IACrE,OAAO,CAACC;QACN,IAAID,aAAaE,QAAQ,IAAI,CAACD,OAAOE,YAAY,IAAIF,OAAOE,YAAY,CAACC,OAAO,CAACC,MAAM,GAAG,GACxF,OAAOJ;QAET,OAAO;YACL,GAAGA,MAAM;YACTK,OAAO;gBACL,GAAIL,OAAOK,KAAK,IAAI,CAAC,CAAC;gBACtBC,QAAQ;oBACN,GAAIN,OAAOK,KAAK,EAAEC,UAAU,CAAC,CAAC;oBAC9BR,YAAY;wBACVS,WAAWR,aAAaQ,SAAS,CAACC,GAAG,CAAC,CAAC,EAAEC,GAAG,EAAE,GAAM,CAAA;gCAAEA;4BAAI,CAAA;oBAC5D;gBACF;YACF;YACAC,aACEV,OAAOU,WAAW,EAAEF,IAAI,CAACG;gBACvB,IAAI,CAACZ,aAAaW,WAAW,CAACE,QAAQ,CAACD,WAAWE,IAAI,GAAG,OAAOF;gBAEhE,OAAO;oBACL,GAAGA,UAAU;oBACbN,OAAO;wBACL,GAAIM,WAAWN,KAAK,IAAI,CAAC,CAAC;wBAC1BS,YAAY;4BACV,GAAIH,WAAWN,KAAK,EAAES,cAAc,CAAC,CAAC;4BACtCC,MAAM;gCACJ,GAAIJ,WAAWN,KAAK,EAAES,YAAYC,QAAQ,CAAC,CAAC;gCAC5CC,YAAYtB;4BACd;wBACF;oBACF;gBACF;YACF,MAAM,EAAE;YACVY,QAAQ;gBACN,GAAIN,OAAOM,MAAM,IAAI,CAAC,CAAC;gBACvBR,YAAY;oBACVS,WAAWR,aAAaQ,SAAS;gBACnC;YACF;YACAU,WAAW;mBACLjB,OAAOiB,SAAS,IAAI,EAAE;gBAC1B;oBACEC,SAAStB;oBACTuB,QAAQ;oBACRC,MAAM;gBACR;aACD;YACDC,SACErB,OAAOqB,OAAO,EAAEb,IAAI,CAACc;gBACnB,IAAI,CAACvB,aAAasB,OAAO,CAACT,QAAQ,CAACU,OAAOT,IAAI,GAAG,OAAOS;gBAExD,OAAO;oBACL,GAAGA,MAAM;oBACTjB,OAAO;wBACL,GAAIiB,OAAOjB,KAAK,IAAI,CAAC,CAAC;wBACtBS,YAAY;4BACV,GAAIQ,OAAOjB,KAAK,EAAES,cAAc,CAAC,CAAC;4BAClCS,UAAU;gCACR,GAAID,OAAOjB,KAAK,EAAES,YAAYS,YAAY,CAAC,CAAC;gCAC5CP,YAAYtB;4BACd;wBACF;oBACF;gBACF;YACF,MAAM,EAAE;YACV8B,MAAM;gBACJ,GAAGxB,OAAOwB,IAAI;gBACd7B,cAAc;oBACZ,GAAGF,UAAUO,OAAOwB,IAAI,EAAE7B,gBAAgB,CAAC,GAAGA,aAAa;gBAC7D;YACF;QACF;IACF;AACF,EAAE"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../src/resolvers/copy.ts"],"sourcesContent":["import type { TranslateResolver } from './types';\
|
1
|
+
{"version":3,"sources":["../../src/resolvers/copy.ts"],"sourcesContent":["import type { TranslateResolver } from './types';\n\nexport const copyResolver = (): TranslateResolver => {\n return {\n key: 'copy',\n resolve: (args) => {\n const { texts } = args;\n\n return {\n success: true,\n translatedTexts: texts,\n };\n },\n };\n};\n"],"names":["copyResolver","key","resolve","args","texts","success","translatedTexts"],"rangeMappings":";;;;;;;;;;;","mappings":"AAEA,OAAO,MAAMA,eAAe;IAC1B,OAAO;QACLC,KAAK;QACLC,SAAS,CAACC;YACR,MAAM,EAAEC,KAAK,EAAE,GAAGD;YAElB,OAAO;gBACLE,SAAS;gBACTC,iBAAiBF;YACnB;QACF;IACF;AACF,EAAE"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../src/resolvers/google.ts"],"sourcesContent":["import { chunkArray } from '../utils/chunkArray';\
|
1
|
+
{"version":3,"sources":["../../src/resolvers/google.ts"],"sourcesContent":["import { chunkArray } from '../utils/chunkArray';\nimport type { TranslateResolver } from './types';\n\ntype GoogleResponse = {\n data: {\n data: {\n translations: {\n detectedSourceLanguage: string;\n model: string;\n translatedText: string;\n }[];\n };\n };\n success: boolean;\n};\n\nconst localeToCountryCodeMapper = {\n ua: 'uk',\n};\n\nconst mapLocale = (incoming: string) =>\n incoming in localeToCountryCodeMapper\n ? localeToCountryCodeMapper[incoming as keyof typeof localeToCountryCodeMapper]\n : incoming;\n\nexport type GoogleResolverConfig = {\n apiKey: string;\n /**\n * How many texts to include into 1 request\n * @default 100\n */\n chunkLength?: number;\n};\n\nexport const googleResolver = ({\n apiKey,\n chunkLength = 100,\n}: GoogleResolverConfig): TranslateResolver => {\n return {\n key: 'google',\n resolve: async (args) => {\n const { localeFrom, localeTo, req, texts } = args;\n\n const apiUrl = `https://translation.googleapis.com/language/translate/v2?key=${apiKey}`;\n\n const responses: GoogleResponse[] = await Promise.all(\n chunkArray(texts, chunkLength).map((q) =>\n fetch(apiUrl, {\n body: JSON.stringify({\n q,\n source: mapLocale(localeFrom),\n target: mapLocale(localeTo),\n }),\n headers: {\n 'Content-Type': 'application/json',\n },\n method: 'POST',\n }).then(async (res) => {\n const data = await res.json();\n\n if (!res.ok)\n req.payload.logger.info({\n googleResponse: data,\n message: `An error occurred when trying to translate the data using Google API`,\n });\n\n return {\n data,\n success: res.ok,\n };\n }),\n ),\n );\n\n if (responses.some((res) => !res.success)) {\n return {\n success: false,\n };\n }\n\n const translatedTexts = responses\n .flatMap((chunk) => chunk.data.data.translations)\n .map((translation) => translation.translatedText);\n\n return {\n success: true,\n translatedTexts,\n };\n },\n };\n};\n"],"names":["chunkArray","localeToCountryCodeMapper","ua","mapLocale","incoming","googleResolver","apiKey","chunkLength","key","resolve","args","localeFrom","localeTo","req","texts","apiUrl","responses","Promise","all","map","q","fetch","body","JSON","stringify","source","target","headers","method","then","res","data","json","ok","payload","logger","info","googleResponse","message","success","some","translatedTexts","flatMap","chunk","translations","translation","translatedText"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAAA,SAASA,UAAU,QAAQ,sBAAsB;AAgBjD,MAAMC,4BAA4B;IAChCC,IAAI;AACN;AAEA,MAAMC,YAAY,CAACC,WACjBA,YAAYH,4BACRA,yBAAyB,CAACG,SAAmD,GAC7EA;AAWN,OAAO,MAAMC,iBAAiB,CAAC,EAC7BC,MAAM,EACNC,cAAc,GAAG,EACI;IACrB,OAAO;QACLC,KAAK;QACLC,SAAS,OAAOC;YACd,MAAM,EAAEC,UAAU,EAAEC,QAAQ,EAAEC,GAAG,EAAEC,KAAK,EAAE,GAAGJ;YAE7C,MAAMK,SAAS,CAAC,6DAA6D,EAAET,OAAO,CAAC;YAEvF,MAAMU,YAA8B,MAAMC,QAAQC,GAAG,CACnDlB,WAAWc,OAAOP,aAAaY,GAAG,CAAC,CAACC,IAClCC,MAAMN,QAAQ;oBACZO,MAAMC,KAAKC,SAAS,CAAC;wBACnBJ;wBACAK,QAAQtB,UAAUQ;wBAClBe,QAAQvB,UAAUS;oBACpB;oBACAe,SAAS;wBACP,gBAAgB;oBAClB;oBACAC,QAAQ;gBACV,GAAGC,IAAI,CAAC,OAAOC;oBACb,MAAMC,OAAO,MAAMD,IAAIE,IAAI;oBAE3B,IAAI,CAACF,IAAIG,EAAE,EACTpB,IAAIqB,OAAO,CAACC,MAAM,CAACC,IAAI,CAAC;wBACtBC,gBAAgBN;wBAChBO,SAAS,CAAC,oEAAoE,CAAC;oBACjF;oBAEF,OAAO;wBACLP;wBACAQ,SAAST,IAAIG,EAAE;oBACjB;gBACF;YAIJ,IAAIjB,UAAUwB,IAAI,CAAC,CAACV,MAAQ,CAACA,IAAIS,OAAO,GAAG;gBACzC,OAAO;oBACLA,SAAS;gBACX;YACF;YAEA,MAAME,kBAAkBzB,UACrB0B,OAAO,CAAC,CAACC,QAAUA,MAAMZ,IAAI,CAACA,IAAI,CAACa,YAAY,EAC/CzB,GAAG,CAAC,CAAC0B,cAAgBA,YAAYC,cAAc;YAElD,OAAO;gBACLP,SAAS;gBACTE;YACF;QACF;IACF;AACF,EAAE"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../src/resolvers/openAI.ts"],"sourcesContent":["import { chunkArray } from '../utils/chunkArray';\
|
1
|
+
{"version":3,"sources":["../../src/resolvers/openAI.ts"],"sourcesContent":["import { chunkArray } from '../utils/chunkArray';\nimport type { TranslateResolver } from './types';\n\nexport type OpenAIPrompt = (args: {\n localeFrom: string;\n localeTo: string;\n texts: string[];\n}) => string;\n\nexport type OpenAIResolverConfig = {\n apiKey: string;\n /**\n * How many texts to include into 1 request\n * @default 100\n */\n chunkLength?: number;\n /**\n * @default \"gpt-3.5-turbo\"\n */\n model?: string;\n promt?: OpenAIPrompt;\n};\n\ntype OpenAIResponse = {\n choices: {\n message: {\n content: string;\n };\n }[];\n};\n\nconst defaultPromt: OpenAIPrompt = ({ localeFrom, localeTo, texts }) => {\n return `Translate me the following array: ${JSON.stringify(texts)} in locale=${localeFrom} to locale ${localeTo}, respond me with the same array structure`;\n};\n\nexport const openAIResolver = ({\n apiKey,\n chunkLength = 100,\n model = 'gpt-3.5-turbo',\n promt = defaultPromt,\n}: OpenAIResolverConfig): TranslateResolver => {\n return {\n key: 'openai',\n resolve: async ({ localeFrom, localeTo, req, texts }) => {\n const apiUrl = 'https://api.openai.com/v1/chat/completions';\n\n try {\n const respones: {\n data: OpenAIResponse;\n success: boolean;\n }[] = await Promise.all(\n chunkArray(texts, chunkLength).map((texts) => {\n return fetch(apiUrl, {\n body: JSON.stringify({\n messages: [\n {\n content: promt({ localeFrom, localeTo, texts }),\n role: 'user',\n },\n ],\n model,\n }),\n headers: {\n Authorization: `Bearer ${apiKey}`,\n 'Content-Type': 'application/json',\n },\n method: 'post',\n }).then(async (res) => {\n const data = await res.json();\n\n if (!res.ok)\n req.payload.logger.info({\n message: `An error occurred when trying to translate the data using OpenAI API`,\n openAIresponse: data,\n });\n\n return {\n data,\n success: res.ok,\n };\n });\n }),\n );\n\n const translated: string[] = [];\n\n for (const { data, success } of respones) {\n if (!success)\n return {\n success: false as const,\n };\n\n const content = data?.choices?.[0]?.message?.content;\n\n if (!content) {\n req.payload.logger.info(\n `An error occurred when trying to translate the data using OpenAI API - missing content in the response`,\n );\n\n return {\n success: false as const,\n };\n }\n\n const translatedChunk: string[] = JSON.parse(content);\n\n if (!Array.isArray(translatedChunk)) {\n req.payload.logger.info({\n data: translatedChunk,\n message: `An error occurred when trying to translate the data using OpenAI API - parsed content is not an array`,\n });\n\n return {\n success: false as const,\n };\n }\n\n for (const text of translatedChunk) {\n if (typeof text !== 'string') {\n req.payload.logger.info({\n data: text,\n message: `An error occurred when trying to translate the data using OpenAI API - parsed content is not an array`,\n });\n\n return {\n success: false as const,\n };\n }\n\n translated.push(text);\n }\n }\n\n return {\n success: true as const,\n translatedTexts: translated,\n };\n } catch (e) {\n if (e instanceof Error) {\n req.payload.logger.info({\n message: `An error occurred when trying to translate the data using OpenAI API`,\n originalErr: e.message,\n });\n }\n\n return { success: false as const };\n }\n },\n };\n};\n"],"names":["chunkArray","defaultPromt","localeFrom","localeTo","texts","JSON","stringify","openAIResolver","apiKey","chunkLength","model","promt","key","resolve","req","apiUrl","respones","Promise","all","map","fetch","body","messages","content","role","headers","Authorization","method","then","res","data","json","ok","payload","logger","info","message","openAIresponse","success","translated","choices","translatedChunk","parse","Array","isArray","text","push","translatedTexts","e","Error","originalErr"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAAA,SAASA,UAAU,QAAQ,sBAAsB;AA+BjD,MAAMC,eAA6B,CAAC,EAAEC,UAAU,EAAEC,QAAQ,EAAEC,KAAK,EAAE;IACjE,OAAO,CAAC,kCAAkC,EAAEC,KAAKC,SAAS,CAACF,OAAO,WAAW,EAAEF,WAAW,WAAW,EAAEC,SAAS,0CAA0C,CAAC;AAC7J;AAEA,OAAO,MAAMI,iBAAiB,CAAC,EAC7BC,MAAM,EACNC,cAAc,GAAG,EACjBC,QAAQ,eAAe,EACvBC,QAAQV,YAAY,EACC;IACrB,OAAO;QACLW,KAAK;QACLC,SAAS,OAAO,EAAEX,UAAU,EAAEC,QAAQ,EAAEW,GAAG,EAAEV,KAAK,EAAE;YAClD,MAAMW,SAAS;YAEf,IAAI;gBACF,MAAMC,WAGA,MAAMC,QAAQC,GAAG,CACrBlB,WAAWI,OAAOK,aAAaU,GAAG,CAAC,CAACf;oBAClC,OAAOgB,MAAML,QAAQ;wBACnBM,MAAMhB,KAAKC,SAAS,CAAC;4BACnBgB,UAAU;gCACR;oCACEC,SAASZ,MAAM;wCAAET;wCAAYC;wCAAUC;oCAAM;oCAC7CoB,MAAM;gCACR;6BACD;4BACDd;wBACF;wBACAe,SAAS;4BACPC,eAAe,CAAC,OAAO,EAAElB,OAAO,CAAC;4BACjC,gBAAgB;wBAClB;wBACAmB,QAAQ;oBACV,GAAGC,IAAI,CAAC,OAAOC;wBACb,MAAMC,OAAO,MAAMD,IAAIE,IAAI;wBAE3B,IAAI,CAACF,IAAIG,EAAE,EACTlB,IAAImB,OAAO,CAACC,MAAM,CAACC,IAAI,CAAC;4BACtBC,SAAS,CAAC,oEAAoE,CAAC;4BAC/EC,gBAAgBP;wBAClB;wBAEF,OAAO;4BACLA;4BACAQ,SAAST,IAAIG,EAAE;wBACjB;oBACF;gBACF;gBAGF,MAAMO,aAAuB,EAAE;gBAE/B,KAAK,MAAM,EAAET,IAAI,EAAEQ,OAAO,EAAE,IAAItB,SAAU;oBACxC,IAAI,CAACsB,SACH,OAAO;wBACLA,SAAS;oBACX;oBAEF,MAAMf,UAAUO,MAAMU,SAAS,CAAC,EAAE,EAAEJ,SAASb;oBAE7C,IAAI,CAACA,SAAS;wBACZT,IAAImB,OAAO,CAACC,MAAM,CAACC,IAAI,CACrB,CAAC,sGAAsG,CAAC;wBAG1G,OAAO;4BACLG,SAAS;wBACX;oBACF;oBAEA,MAAMG,kBAA4BpC,KAAKqC,KAAK,CAACnB;oBAE7C,IAAI,CAACoB,MAAMC,OAAO,CAACH,kBAAkB;wBACnC3B,IAAImB,OAAO,CAACC,MAAM,CAACC,IAAI,CAAC;4BACtBL,MAAMW;4BACNL,SAAS,CAAC,qGAAqG,CAAC;wBAClH;wBAEA,OAAO;4BACLE,SAAS;wBACX;oBACF;oBAEA,KAAK,MAAMO,QAAQJ,gBAAiB;wBAClC,IAAI,OAAOI,SAAS,UAAU;4BAC5B/B,IAAImB,OAAO,CAACC,MAAM,CAACC,IAAI,CAAC;gCACtBL,MAAMe;gCACNT,SAAS,CAAC,qGAAqG,CAAC;4BAClH;4BAEA,OAAO;gCACLE,SAAS;4BACX;wBACF;wBAEAC,WAAWO,IAAI,CAACD;oBAClB;gBACF;gBAEA,OAAO;oBACLP,SAAS;oBACTS,iBAAiBR;gBACnB;YACF,EAAE,OAAOS,GAAG;gBACV,IAAIA,aAAaC,OAAO;oBACtBnC,IAAImB,OAAO,CAACC,MAAM,CAACC,IAAI,CAAC;wBACtBC,SAAS,CAAC,oEAAoE,CAAC;wBAC/Ec,aAAaF,EAAEZ,OAAO;oBACxB;gBACF;gBAEA,OAAO;oBAAEE,SAAS;gBAAe;YACnC;QACF;IACF;AACF,EAAE"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../src/resolvers/types.ts"],"sourcesContent":["import type { PayloadRequest } from 'payload/types';\
|
1
|
+
{"version":3,"sources":["../../src/resolvers/types.ts"],"sourcesContent":["import type { PayloadRequest } from 'payload/types';\n\nexport type TranslateResolverArgs = {\n /** Locale to translate from */\n localeFrom: string;\n /** Locale to translate to */\n localeTo: string;\n req: PayloadRequest;\n texts: string[];\n};\n\nexport type TranslateResolverResponse =\n | {\n success: false;\n }\n | {\n success: true;\n translatedTexts: string[];\n };\n\nexport type TranslateResolver = {\n key: string;\n resolve: (\n args: TranslateResolverArgs,\n ) => Promise<TranslateResolverResponse> | TranslateResolverResponse;\n};\n"],"names":[],"rangeMappings":"","mappings":"AAoBA,WAKE"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../src/translate/endpoint.ts"],"sourcesContent":["import type { PayloadHandler } from 'payload/config';\
|
1
|
+
{"version":3,"sources":["../../src/translate/endpoint.ts"],"sourcesContent":["import type { PayloadHandler } from 'payload/config';\nimport { APIError } from 'payload/errors';\n\nimport { translateOperation } from './operation';\nimport type { TranslateEndpointArgs } from './types';\n\nexport const translateEndpoint: PayloadHandler = async (req) => {\n if (!req.json) throw new APIError('Content-Type should be json');\n\n const args: TranslateEndpointArgs = await req.json();\n\n const { collectionSlug, emptyOnly, globalSlug, id, locale, localeFrom, resolver } = args;\n\n const result = await translateOperation({\n collectionSlug,\n emptyOnly,\n globalSlug,\n id,\n locale,\n localeFrom,\n overrideAccess: false,\n req,\n resolver,\n update: false,\n });\n\n return Response.json(result);\n};\n"],"names":["APIError","translateOperation","translateEndpoint","req","json","args","collectionSlug","emptyOnly","globalSlug","id","locale","localeFrom","resolver","result","overrideAccess","update","Response"],"rangeMappings":";;;;;;;;;;;;;;;;;;;","mappings":"AACA,SAASA,QAAQ,QAAQ,iBAAiB;AAE1C,SAASC,kBAAkB,QAAQ,cAAc;AAGjD,OAAO,MAAMC,oBAAoC,OAAOC;IACtD,IAAI,CAACA,IAAIC,IAAI,EAAE,MAAM,IAAIJ,SAAS;IAElC,MAAMK,OAA8B,MAAMF,IAAIC,IAAI;IAElD,MAAM,EAAEE,cAAc,EAAEC,SAAS,EAAEC,UAAU,EAAEC,EAAE,EAAEC,MAAM,EAAEC,UAAU,EAAEC,QAAQ,EAAE,GAAGP;IAEpF,MAAMQ,SAAS,MAAMZ,mBAAmB;QACtCK;QACAC;QACAC;QACAC;QACAC;QACAC;QACAG,gBAAgB;QAChBX;QACAS;QACAG,QAAQ;IACV;IAEA,OAAOC,SAASZ,IAAI,CAACS;AACvB,EAAE"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../src/translate/findEntityWithConfig.ts"],"sourcesContent":["import { APIError } from 'payload/errors';\
|
1
|
+
{"version":3,"sources":["../../src/translate/findEntityWithConfig.ts"],"sourcesContent":["import { APIError } from 'payload/errors';\nimport type {\n PayloadRequest,\n SanitizedCollectionConfig,\n SanitizedGlobalConfig,\n TypeWithID,\n} from 'payload/types';\n\ntype Args = {\n collectionSlug?: string;\n globalSlug?: string;\n id?: number | string;\n locale: string;\n overrideAccess?: boolean;\n req: PayloadRequest;\n};\n\nconst findConfigBySlug = (\n slug: string,\n enities: SanitizedCollectionConfig[] | SanitizedGlobalConfig[],\n) => enities.find((entity) => entity.slug === slug);\n\nexport const findEntityWithConfig = async (\n args: Args,\n): Promise<{\n config: SanitizedCollectionConfig | SanitizedGlobalConfig;\n doc: Record<string, unknown> & TypeWithID;\n}> => {\n const { collectionSlug, globalSlug, id, locale, overrideAccess, req } = args;\n\n if (!collectionSlug && !globalSlug) throw new APIError('Bad Request', 400);\n\n const { payload } = req;\n\n const { config } = payload;\n\n const isGlobal = !!globalSlug;\n\n if (!isGlobal && !id) throw new APIError('Bad Request', 400);\n\n const entityConfig = isGlobal\n ? findConfigBySlug(globalSlug, config.globals)\n : findConfigBySlug(collectionSlug as string, config.collections);\n\n if (!entityConfig) throw new APIError('Bad Request', 400);\n\n const docPromise = isGlobal\n ? payload.findGlobal({\n depth: 0,\n locale,\n overrideAccess,\n req,\n slug: args.globalSlug as string,\n })\n : payload.findByID({\n collection: collectionSlug as string,\n depth: 0,\n id: id as number | string,\n locale,\n overrideAccess,\n req,\n });\n\n return {\n config: entityConfig,\n doc: await docPromise,\n };\n};\n"],"names":["APIError","findConfigBySlug","slug","enities","find","entity","findEntityWithConfig","args","collectionSlug","globalSlug","id","locale","overrideAccess","req","payload","config","isGlobal","entityConfig","globals","collections","docPromise","findGlobal","depth","findByID","collection","doc"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAAA,SAASA,QAAQ,QAAQ,iBAAiB;AAiB1C,MAAMC,mBAAmB,CACvBC,MACAC,UACGA,QAAQC,IAAI,CAAC,CAACC,SAAWA,OAAOH,IAAI,KAAKA;AAE9C,OAAO,MAAMI,uBAAuB,OAClCC;IAKA,MAAM,EAAEC,cAAc,EAAEC,UAAU,EAAEC,EAAE,EAAEC,MAAM,EAAEC,cAAc,EAAEC,GAAG,EAAE,GAAGN;IAExE,IAAI,CAACC,kBAAkB,CAACC,YAAY,MAAM,IAAIT,SAAS,eAAe;IAEtE,MAAM,EAAEc,OAAO,EAAE,GAAGD;IAEpB,MAAM,EAAEE,MAAM,EAAE,GAAGD;IAEnB,MAAME,WAAW,CAAC,CAACP;IAEnB,IAAI,CAACO,YAAY,CAACN,IAAI,MAAM,IAAIV,SAAS,eAAe;IAExD,MAAMiB,eAAeD,WACjBf,iBAAiBQ,YAAYM,OAAOG,OAAO,IAC3CjB,iBAAiBO,gBAA0BO,OAAOI,WAAW;IAEjE,IAAI,CAACF,cAAc,MAAM,IAAIjB,SAAS,eAAe;IAErD,MAAMoB,aAAaJ,WACfF,QAAQO,UAAU,CAAC;QACjBC,OAAO;QACPX;QACAC;QACAC;QACAX,MAAMK,KAAKE,UAAU;IACvB,KACAK,QAAQS,QAAQ,CAAC;QACfC,YAAYhB;QACZc,OAAO;QACPZ,IAAIA;QACJC;QACAC;QACAC;IACF;IAEJ,OAAO;QACLE,QAAQE;QACRQ,KAAK,MAAML;IACb;AACF,EAAE"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../src/translate/operation.ts"],"sourcesContent":["import { APIError } from 'payload/errors';\
|
1
|
+
{"version":3,"sources":["../../src/translate/operation.ts"],"sourcesContent":["import { APIError } from 'payload/errors';\nimport type { Payload, PayloadRequest } from 'payload/types';\n\nimport type { TranslateResolver } from '../resolvers/types';\nimport { findEntityWithConfig } from './findEntityWithConfig';\nimport { traverseFields } from './traverseFields';\nimport type { TranslateArgs, TranslateResult, ValueToTranslate } from './types';\nimport { updateEntity } from './updateEntity';\n\nexport type TranslateOperationArgs = (\n | {\n payload: Payload;\n }\n | {\n req: PayloadRequest;\n }\n) &\n TranslateArgs;\n\nexport const translateOperation = async (args: TranslateOperationArgs) => {\n const req: PayloadRequest =\n 'req' in args\n ? args.req\n : ({\n payload: args.payload,\n } as PayloadRequest);\n\n const { collectionSlug, globalSlug, id, locale, localeFrom, overrideAccess } = args;\n\n const { config, doc: dataFrom } = await findEntityWithConfig({\n collectionSlug,\n globalSlug,\n id,\n locale: localeFrom,\n req,\n });\n\n const resolver = (\n (req.payload.config.custom?.translator?.resolvers as TranslateResolver[]) ?? []\n ).find((each) => each.key === args.resolver);\n\n if (!resolver) throw new APIError(`Resolver with the key ${args.resolver} was not found`);\n\n const valuesToTranslate: ValueToTranslate[] = [];\n\n let translatedData = args.data;\n\n if (!translatedData) {\n const { doc } = await findEntityWithConfig({\n collectionSlug,\n globalSlug,\n id,\n locale,\n overrideAccess,\n req,\n });\n\n translatedData = doc;\n }\n\n traverseFields({\n dataFrom,\n emptyOnly: args.emptyOnly,\n fields: config.fields,\n translatedData,\n valuesToTranslate,\n });\n\n const resolveResult = await resolver.resolve({\n localeFrom: args.localeFrom,\n localeTo: args.locale,\n req,\n texts: valuesToTranslate.map((each) => each.value),\n });\n\n let result: TranslateResult;\n\n if (!resolveResult.success) {\n result = {\n success: false,\n };\n } else {\n resolveResult.translatedTexts.forEach((translated, index) => {\n valuesToTranslate[index].onTranslate(translated);\n });\n\n if (args.update) {\n await updateEntity({\n collectionSlug,\n data: translatedData,\n depth: 0,\n globalSlug,\n id,\n locale,\n overrideAccess,\n req,\n });\n }\n\n result = {\n success: true,\n translatedData,\n };\n }\n\n return result;\n};\n"],"names":["APIError","findEntityWithConfig","traverseFields","updateEntity","translateOperation","args","req","payload","collectionSlug","globalSlug","id","locale","localeFrom","overrideAccess","config","doc","dataFrom","resolver","custom","translator","resolvers","find","each","key","valuesToTranslate","translatedData","data","emptyOnly","fields","resolveResult","resolve","localeTo","texts","map","value","result","success","translatedTexts","forEach","translated","index","onTranslate","update","depth"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAAA,SAASA,QAAQ,QAAQ,iBAAiB;AAI1C,SAASC,oBAAoB,QAAQ,yBAAyB;AAC9D,SAASC,cAAc,QAAQ,mBAAmB;AAElD,SAASC,YAAY,QAAQ,iBAAiB;AAY9C,OAAO,MAAMC,qBAAqB,OAAOC;IACvC,MAAMC,MACJ,SAASD,OACLA,KAAKC,GAAG,GACP;QACCC,SAASF,KAAKE,OAAO;IACvB;IAEN,MAAM,EAAEC,cAAc,EAAEC,UAAU,EAAEC,EAAE,EAAEC,MAAM,EAAEC,UAAU,EAAEC,cAAc,EAAE,GAAGR;IAE/E,MAAM,EAAES,MAAM,EAAEC,KAAKC,QAAQ,EAAE,GAAG,MAAMf,qBAAqB;QAC3DO;QACAC;QACAC;QACAC,QAAQC;QACRN;IACF;IAEA,MAAMW,WAAW,AACf,CAAA,AAACX,IAAIC,OAAO,CAACO,MAAM,CAACI,MAAM,EAAEC,YAAYC,aAAqC,EAAE,AAAD,EAC9EC,IAAI,CAAC,CAACC,OAASA,KAAKC,GAAG,KAAKlB,KAAKY,QAAQ;IAE3C,IAAI,CAACA,UAAU,MAAM,IAAIjB,SAAS,CAAC,sBAAsB,EAAEK,KAAKY,QAAQ,CAAC,cAAc,CAAC;IAExF,MAAMO,oBAAwC,EAAE;IAEhD,IAAIC,iBAAiBpB,KAAKqB,IAAI;IAE9B,IAAI,CAACD,gBAAgB;QACnB,MAAM,EAAEV,GAAG,EAAE,GAAG,MAAMd,qBAAqB;YACzCO;YACAC;YACAC;YACAC;YACAE;YACAP;QACF;QAEAmB,iBAAiBV;IACnB;IAEAb,eAAe;QACbc;QACAW,WAAWtB,KAAKsB,SAAS;QACzBC,QAAQd,OAAOc,MAAM;QACrBH;QACAD;IACF;IAEA,MAAMK,gBAAgB,MAAMZ,SAASa,OAAO,CAAC;QAC3ClB,YAAYP,KAAKO,UAAU;QAC3BmB,UAAU1B,KAAKM,MAAM;QACrBL;QACA0B,OAAOR,kBAAkBS,GAAG,CAAC,CAACX,OAASA,KAAKY,KAAK;IACnD;IAEA,IAAIC;IAEJ,IAAI,CAACN,cAAcO,OAAO,EAAE;QAC1BD,SAAS;YACPC,SAAS;QACX;IACF,OAAO;QACLP,cAAcQ,eAAe,CAACC,OAAO,CAAC,CAACC,YAAYC;YACjDhB,iBAAiB,CAACgB,MAAM,CAACC,WAAW,CAACF;QACvC;QAEA,IAAIlC,KAAKqC,MAAM,EAAE;YACf,MAAMvC,aAAa;gBACjBK;gBACAkB,MAAMD;gBACNkB,OAAO;gBACPlC;gBACAC;gBACAC;gBACAE;gBACAP;YACF;QACF;QAEA6B,SAAS;YACPC,SAAS;YACTX;QACF;IACF;IAEA,OAAOU;AACT,EAAE"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../src/translate/traverseFields.ts"],"sourcesContent":["import ObjectID from 'bson-objectid';\r\nimport { APIError } from 'payload/errors';\r\nimport { type Field, tabHasName } from 'payload/types';\r\n\r\nimport { isEmpty } from '../utils/isEmpty';\r\nimport { traverseRichText } from './traverseRichText';\r\nimport type { ValueToTranslate } from './types';\r\n\r\nexport const traverseFields = ({\r\n dataFrom,\r\n emptyOnly,\r\n fields,\r\n localizedParent,\r\n siblingDataFrom,\r\n siblingDataTranslated,\r\n translatedData,\r\n valuesToTranslate,\r\n}: {\r\n dataFrom: Record<string, unknown>;\r\n emptyOnly?: boolean;\r\n fields: Field[];\r\n localizedParent?: boolean;\r\n siblingDataFrom?: Record<string, unknown>;\r\n siblingDataTranslated?: Record<string, unknown>;\r\n translatedData: Record<string, unknown>;\r\n valuesToTranslate: ValueToTranslate[];\r\n}) => {\r\n siblingDataFrom = siblingDataFrom ?? dataFrom;\r\n siblingDataTranslated = siblingDataTranslated ?? translatedData;\r\n\r\n fields.forEach((field) => {\r\n switch (field.type) {\r\n case 'tabs':\r\n field.tabs.forEach((tab) => {\r\n const hasName = tabHasName(tab);\r\n\r\n const tabDataFrom = hasName\r\n ? (siblingDataFrom[tab.name] as Record<string, unknown>)\r\n : siblingDataFrom;\r\n\r\n if (!tabDataFrom) return;\r\n\r\n const tabDataTranslated = hasName\r\n ? (siblingDataTranslated[tab.name] as Record<string, unknown>) ?? {}\r\n : siblingDataTranslated;\r\n\r\n traverseFields({\r\n dataFrom,\r\n emptyOnly,\r\n fields: tab.fields,\r\n localizedParent: tab.localized,\r\n siblingDataFrom: tabDataFrom,\r\n siblingDataTranslated: tabDataTranslated,\r\n translatedData,\r\n valuesToTranslate,\r\n });\r\n });\r\n\r\n break;\r\n\r\n case 'group':\r\n const groupDataFrom = siblingDataFrom[field.name] as Record<string, unknown>;\r\n\r\n if (!groupDataFrom) break;\r\n\r\n const groupDataTranslated =\r\n (siblingDataTranslated[field.name] as Record<string, unknown>) ?? {};\r\n\r\n traverseFields({\r\n dataFrom,\r\n emptyOnly,\r\n fields: field.fields,\r\n localizedParent: field.localized,\r\n siblingDataFrom: groupDataFrom,\r\n siblingDataTranslated: groupDataTranslated,\r\n translatedData,\r\n valuesToTranslate,\r\n });\r\n\r\n break;\r\n\r\n case 'array':\r\n const arrayDataFrom = siblingDataFrom[field.name] as {\r\n id: string;\r\n }[];\r\n\r\n if (isEmpty(arrayDataFrom)) break;\r\n\r\n const arrayDataTranslated = [] as { id: string }[];\r\n\r\n const currentArrayDataInTranslated = Array.isArray(siblingDataTranslated[field.name])\r\n ? (siblingDataTranslated[field.name] as { id: string }[])\r\n : undefined;\r\n\r\n arrayDataFrom.forEach((item, index) => {\r\n const currentArrayItemInTranslated = currentArrayDataInTranslated?.[index];\r\n\r\n arrayDataTranslated.push({\r\n // ensure ids are different, Postgres doesn't like the same.\r\n ...(currentArrayItemInTranslated ?? {}),\r\n id: currentArrayItemInTranslated?.id ?? ObjectID().toHexString(),\r\n });\r\n\r\n traverseFields({\r\n dataFrom,\r\n emptyOnly,\r\n fields: field.fields,\r\n localizedParent: localizedParent ?? field.localized,\r\n siblingDataFrom: item,\r\n siblingDataTranslated: arrayDataTranslated[index],\r\n translatedData,\r\n valuesToTranslate,\r\n });\r\n });\r\n\r\n siblingDataTranslated[field.name] = arrayDataTranslated;\r\n\r\n break;\r\n\r\n case 'blocks':\r\n const blockDataFrom = siblingDataFrom[field.name] as { blockType: string; id: string }[];\r\n\r\n if (isEmpty(blockDataFrom)) break;\r\n\r\n const currentBlockDataInTranslated = Array.isArray(siblingDataTranslated[field.name])\r\n ? (siblingDataTranslated[field.name] as { id: string }[])\r\n : undefined;\r\n\r\n const blockDataTranslated = [] as { blockType: string; id: string }[];\r\n\r\n blockDataFrom.forEach((item, index) => {\r\n const currentBlockItemInTranslated = currentBlockDataInTranslated?.[index];\r\n\r\n blockDataTranslated.push({\r\n blockType: item.blockType,\r\n // ensure ids are different, needed with Postgres\r\n ...(currentBlockItemInTranslated ?? {}),\r\n id: currentBlockItemInTranslated?.id ?? ObjectID().toHexString(),\r\n });\r\n\r\n const block = field.blocks.find((each) => each.slug === item.blockType);\r\n\r\n if (!block) throw new APIError(`Block with slug ${item.blockType} is not found`);\r\n\r\n traverseFields({\r\n dataFrom,\r\n emptyOnly,\r\n fields: block.fields,\r\n localizedParent,\r\n siblingDataFrom: item,\r\n siblingDataTranslated: blockDataTranslated[index],\r\n translatedData,\r\n valuesToTranslate,\r\n });\r\n });\r\n\r\n siblingDataTranslated[field.name] = blockDataTranslated;\r\n\r\n break;\r\n\r\n case 'collapsible':\r\n case 'row':\r\n traverseFields({\r\n dataFrom,\r\n emptyOnly,\r\n fields: field.fields,\r\n localizedParent,\r\n siblingDataFrom,\r\n siblingDataTranslated,\r\n translatedData,\r\n valuesToTranslate,\r\n });\r\n break;\r\n\r\n // long ass cases here we have\r\n case 'date':\r\n case 'checkbox':\r\n case 'json':\r\n case 'code':\r\n case 'email':\r\n case 'number':\r\n case 'point':\r\n case 'radio':\r\n case 'relationship':\r\n case 'select':\r\n case 'upload':\r\n siblingDataTranslated[field.name] = siblingDataFrom[field.name];\r\n\r\n break;\r\n\r\n case 'text':\r\n case 'textarea':\r\n if (!field.localized && !localizedParent && isEmpty(siblingDataFrom[field.name])) return;\r\n if (emptyOnly && siblingDataTranslated[field.name]) return;\r\n\r\n valuesToTranslate.push({\r\n onTranslate: (translated: string) => {\r\n siblingDataTranslated[field.name] = translated;\r\n },\r\n value: siblingDataFrom[field.name],\r\n });\r\n break;\r\n\r\n case 'richText':\r\n if (!field.localized && !localizedParent && isEmpty(siblingDataFrom[field.name])) break;\r\n if (emptyOnly && siblingDataTranslated[field.name]) return;\r\n const richTextDataFrom = siblingDataFrom[field.name] as object;\r\n\r\n siblingDataTranslated[field.name] = richTextDataFrom;\r\n const isSlate = Array.isArray(richTextDataFrom);\r\n\r\n const isLexical = 'root' in richTextDataFrom;\r\n\r\n if (!isSlate && !isLexical) break;\r\n\r\n const root = (\r\n isLexical\r\n ? (siblingDataTranslated[field.name] as Record<string, unknown>).root\r\n : (siblingDataTranslated[field.name] as unknown[])?.[0]\r\n ) as Record<string, unknown>;\r\n\r\n traverseRichText({\r\n onText: (siblingData) => {\r\n valuesToTranslate.push({\r\n onTranslate: (translated: string) => {\r\n siblingData.text = translated;\r\n },\r\n value: siblingData.text,\r\n });\r\n },\r\n root,\r\n });\r\n\r\n break;\r\n\r\n default:\r\n break;\r\n }\r\n });\r\n};\r\n"],"names":["ObjectID","APIError","tabHasName","isEmpty","traverseRichText","traverseFields","dataFrom","emptyOnly","fields","localizedParent","siblingDataFrom","siblingDataTranslated","translatedData","valuesToTranslate","forEach","field","type","tabs","tab","hasName","tabDataFrom","name","tabDataTranslated","localized","groupDataFrom","groupDataTranslated","arrayDataFrom","arrayDataTranslated","currentArrayDataInTranslated","Array","isArray","undefined","item","index","currentArrayItemInTranslated","push","id","toHexString","blockDataFrom","currentBlockDataInTranslated","blockDataTranslated","currentBlockItemInTranslated","blockType","block","blocks","find","each","slug","onTranslate","translated","value","richTextDataFrom","isSlate","isLexical","root","onText","siblingData","text"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
|
1
|
+
{"version":3,"sources":["../../src/translate/traverseFields.ts"],"sourcesContent":["import ObjectID from 'bson-objectid';\nimport { APIError } from 'payload/errors';\nimport { type Field, tabHasName } from 'payload/types';\n\nimport { isEmpty } from '../utils/isEmpty';\nimport { traverseRichText } from './traverseRichText';\nimport type { ValueToTranslate } from './types';\n\nexport const traverseFields = ({\n dataFrom,\n emptyOnly,\n fields,\n localizedParent,\n siblingDataFrom,\n siblingDataTranslated,\n translatedData,\n valuesToTranslate,\n}: {\n dataFrom: Record<string, unknown>;\n emptyOnly?: boolean;\n fields: Field[];\n localizedParent?: boolean;\n siblingDataFrom?: Record<string, unknown>;\n siblingDataTranslated?: Record<string, unknown>;\n translatedData: Record<string, unknown>;\n valuesToTranslate: ValueToTranslate[];\n}) => {\n siblingDataFrom = siblingDataFrom ?? dataFrom;\n siblingDataTranslated = siblingDataTranslated ?? translatedData;\n\n fields.forEach((field) => {\n switch (field.type) {\n case 'tabs':\n field.tabs.forEach((tab) => {\n const hasName = tabHasName(tab);\n\n const tabDataFrom = hasName\n ? (siblingDataFrom[tab.name] as Record<string, unknown>)\n : siblingDataFrom;\n\n if (!tabDataFrom) return;\n\n const tabDataTranslated = hasName\n ? (siblingDataTranslated[tab.name] as Record<string, unknown>) ?? {}\n : siblingDataTranslated;\n\n traverseFields({\n dataFrom,\n emptyOnly,\n fields: tab.fields,\n localizedParent: tab.localized,\n siblingDataFrom: tabDataFrom,\n siblingDataTranslated: tabDataTranslated,\n translatedData,\n valuesToTranslate,\n });\n });\n\n break;\n\n case 'group':\n const groupDataFrom = siblingDataFrom[field.name] as Record<string, unknown>;\n\n if (!groupDataFrom) break;\n\n const groupDataTranslated =\n (siblingDataTranslated[field.name] as Record<string, unknown>) ?? {};\n\n traverseFields({\n dataFrom,\n emptyOnly,\n fields: field.fields,\n localizedParent: field.localized,\n siblingDataFrom: groupDataFrom,\n siblingDataTranslated: groupDataTranslated,\n translatedData,\n valuesToTranslate,\n });\n\n break;\n\n case 'array':\n const arrayDataFrom = siblingDataFrom[field.name] as {\n id: string;\n }[];\n\n if (isEmpty(arrayDataFrom)) break;\n\n const arrayDataTranslated = [] as { id: string }[];\n\n const currentArrayDataInTranslated = Array.isArray(siblingDataTranslated[field.name])\n ? (siblingDataTranslated[field.name] as { id: string }[])\n : undefined;\n\n arrayDataFrom.forEach((item, index) => {\n const currentArrayItemInTranslated = currentArrayDataInTranslated?.[index];\n\n arrayDataTranslated.push({\n // ensure ids are different, Postgres doesn't like the same.\n ...(currentArrayItemInTranslated ?? {}),\n id: currentArrayItemInTranslated?.id ?? ObjectID().toHexString(),\n });\n\n traverseFields({\n dataFrom,\n emptyOnly,\n fields: field.fields,\n localizedParent: localizedParent ?? field.localized,\n siblingDataFrom: item,\n siblingDataTranslated: arrayDataTranslated[index],\n translatedData,\n valuesToTranslate,\n });\n });\n\n siblingDataTranslated[field.name] = arrayDataTranslated;\n\n break;\n\n case 'blocks':\n const blockDataFrom = siblingDataFrom[field.name] as { blockType: string; id: string }[];\n\n if (isEmpty(blockDataFrom)) break;\n\n const currentBlockDataInTranslated = Array.isArray(siblingDataTranslated[field.name])\n ? (siblingDataTranslated[field.name] as { id: string }[])\n : undefined;\n\n const blockDataTranslated = [] as { blockType: string; id: string }[];\n\n blockDataFrom.forEach((item, index) => {\n const currentBlockItemInTranslated = currentBlockDataInTranslated?.[index];\n\n blockDataTranslated.push({\n blockType: item.blockType,\n // ensure ids are different, needed with Postgres\n ...(currentBlockItemInTranslated ?? {}),\n id: currentBlockItemInTranslated?.id ?? ObjectID().toHexString(),\n });\n\n const block = field.blocks.find((each) => each.slug === item.blockType);\n\n if (!block) throw new APIError(`Block with slug ${item.blockType} is not found`);\n\n traverseFields({\n dataFrom,\n emptyOnly,\n fields: block.fields,\n localizedParent,\n siblingDataFrom: item,\n siblingDataTranslated: blockDataTranslated[index],\n translatedData,\n valuesToTranslate,\n });\n });\n\n siblingDataTranslated[field.name] = blockDataTranslated;\n\n break;\n\n case 'collapsible':\n case 'row':\n traverseFields({\n dataFrom,\n emptyOnly,\n fields: field.fields,\n localizedParent,\n siblingDataFrom,\n siblingDataTranslated,\n translatedData,\n valuesToTranslate,\n });\n break;\n\n // long ass cases here we have\n case 'date':\n case 'checkbox':\n case 'json':\n case 'code':\n case 'email':\n case 'number':\n case 'point':\n case 'radio':\n case 'relationship':\n case 'select':\n case 'upload':\n siblingDataTranslated[field.name] = siblingDataFrom[field.name];\n\n break;\n\n case 'text':\n case 'textarea':\n if (!field.localized && !localizedParent && isEmpty(siblingDataFrom[field.name])) return;\n if (emptyOnly && siblingDataTranslated[field.name]) return;\n\n valuesToTranslate.push({\n onTranslate: (translated: string) => {\n siblingDataTranslated[field.name] = translated;\n },\n value: siblingDataFrom[field.name],\n });\n break;\n\n case 'richText':\n if (!field.localized && !localizedParent && isEmpty(siblingDataFrom[field.name])) break;\n if (emptyOnly && siblingDataTranslated[field.name]) return;\n const richTextDataFrom = siblingDataFrom[field.name] as object;\n\n siblingDataTranslated[field.name] = richTextDataFrom;\n const isSlate = Array.isArray(richTextDataFrom);\n\n const isLexical = 'root' in richTextDataFrom;\n\n if (!isSlate && !isLexical) break;\n\n const root = (\n isLexical\n ? (siblingDataTranslated[field.name] as Record<string, unknown>).root\n : (siblingDataTranslated[field.name] as unknown[])?.[0]\n ) as Record<string, unknown>;\n\n traverseRichText({\n onText: (siblingData) => {\n valuesToTranslate.push({\n onTranslate: (translated: string) => {\n siblingData.text = translated;\n },\n value: siblingData.text,\n });\n },\n root,\n });\n\n break;\n\n default:\n break;\n }\n });\n};\n"],"names":["ObjectID","APIError","tabHasName","isEmpty","traverseRichText","traverseFields","dataFrom","emptyOnly","fields","localizedParent","siblingDataFrom","siblingDataTranslated","translatedData","valuesToTranslate","forEach","field","type","tabs","tab","hasName","tabDataFrom","name","tabDataTranslated","localized","groupDataFrom","groupDataTranslated","arrayDataFrom","arrayDataTranslated","currentArrayDataInTranslated","Array","isArray","undefined","item","index","currentArrayItemInTranslated","push","id","toHexString","blockDataFrom","currentBlockDataInTranslated","blockDataTranslated","currentBlockItemInTranslated","blockType","block","blocks","find","each","slug","onTranslate","translated","value","richTextDataFrom","isSlate","isLexical","root","onText","siblingData","text"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../src/translate/traverseRichText.ts"],"sourcesContent":["export const traverseRichText = ({\
|
1
|
+
{"version":3,"sources":["../../src/translate/traverseRichText.ts"],"sourcesContent":["export const traverseRichText = ({\n onText,\n root,\n siblingData,\n}: {\n onText: (siblingData: Record<string, unknown>) => void;\n root: Record<string, unknown>;\n siblingData?: Record<string, unknown>;\n}) => {\n siblingData = siblingData ?? root;\n\n if (siblingData.text) {\n onText(siblingData);\n }\n\n if (Array.isArray(siblingData?.children)) {\n siblingData.children.forEach((siblingData) => {\n traverseRichText({\n onText,\n root,\n siblingData,\n });\n });\n }\n};\n"],"names":["traverseRichText","onText","root","siblingData","text","Array","isArray","children","forEach"],"rangeMappings":";;;;;;;;;;;;;;","mappings":"AAAA,OAAO,MAAMA,mBAAmB,CAAC,EAC/BC,MAAM,EACNC,IAAI,EACJC,WAAW,EAKZ;IACCA,cAAcA,eAAeD;IAE7B,IAAIC,YAAYC,IAAI,EAAE;QACpBH,OAAOE;IACT;IAEA,IAAIE,MAAMC,OAAO,CAACH,aAAaI,WAAW;QACxCJ,YAAYI,QAAQ,CAACC,OAAO,CAAC,CAACL;YAC5BH,iBAAiB;gBACfC;gBACAC;gBACAC;YACF;QACF;IACF;AACF,EAAE"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../src/translate/types.ts"],"sourcesContent":["export type ValueToTranslate = {\
|
1
|
+
{"version":3,"sources":["../../src/translate/types.ts"],"sourcesContent":["export type ValueToTranslate = {\n onTranslate: (translatedValue: any) => void;\n value: any;\n};\n\nexport type TranslateArgs = {\n collectionSlug?: string;\n data?: Record<string, any>;\n emptyOnly?: boolean;\n globalSlug?: string;\n id?: number | string;\n /** active locale */\n locale: string;\n localeFrom: string;\n overrideAccess?: boolean;\n resolver: string;\n update?: boolean;\n};\n\nexport type TranslateResult =\n | {\n success: false;\n }\n | {\n success: true;\n translatedData: Record<string, any>;\n };\n\nexport type TranslateEndpointArgs = Omit<TranslateArgs, 'data' | 'update'>;\n"],"names":[],"rangeMappings":"","mappings":"AA4BA,WAA2E"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../src/translate/updateEntity.ts"],"sourcesContent":["import { APIError } from 'payload/errors';\
|
1
|
+
{"version":3,"sources":["../../src/translate/updateEntity.ts"],"sourcesContent":["import { APIError } from 'payload/errors';\nimport type { PayloadRequest, TypeWithID } from 'payload/types';\n\ntype Args = {\n collectionSlug?: string;\n data: Record<string, any>;\n depth?: number;\n globalSlug?: string;\n id?: number | string;\n locale: string;\n overrideAccess?: boolean;\n req: PayloadRequest;\n};\n\nexport const updateEntity = ({\n collectionSlug,\n data,\n depth: incomingDepth,\n globalSlug,\n id,\n locale,\n overrideAccess,\n req,\n}: Args): Promise<Record<string, unknown> & TypeWithID> => {\n if (!collectionSlug && !globalSlug) throw new APIError('Bad Request', 400);\n\n const isGlobal = !!globalSlug;\n\n if (!isGlobal && !id) throw new APIError('Bad Request', 400);\n\n const depth = incomingDepth ?? req.payload.config.defaultDepth;\n\n const promise = isGlobal\n ? req.payload.updateGlobal({\n data,\n depth,\n locale,\n overrideAccess,\n req,\n slug: globalSlug as string,\n })\n : req.payload.update({\n collection: collectionSlug as string,\n data,\n depth,\n id: id as number | string,\n locale,\n overrideAccess,\n req,\n });\n\n return promise;\n};\n"],"names":["APIError","updateEntity","collectionSlug","data","depth","incomingDepth","globalSlug","id","locale","overrideAccess","req","isGlobal","payload","config","defaultDepth","promise","updateGlobal","slug","update","collection"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAAA,SAASA,QAAQ,QAAQ,iBAAiB;AAc1C,OAAO,MAAMC,eAAe,CAAC,EAC3BC,cAAc,EACdC,IAAI,EACJC,OAAOC,aAAa,EACpBC,UAAU,EACVC,EAAE,EACFC,MAAM,EACNC,cAAc,EACdC,GAAG,EACE;IACL,IAAI,CAACR,kBAAkB,CAACI,YAAY,MAAM,IAAIN,SAAS,eAAe;IAEtE,MAAMW,WAAW,CAAC,CAACL;IAEnB,IAAI,CAACK,YAAY,CAACJ,IAAI,MAAM,IAAIP,SAAS,eAAe;IAExD,MAAMI,QAAQC,iBAAiBK,IAAIE,OAAO,CAACC,MAAM,CAACC,YAAY;IAE9D,MAAMC,UAAUJ,WACZD,IAAIE,OAAO,CAACI,YAAY,CAAC;QACvBb;QACAC;QACAI;QACAC;QACAC;QACAO,MAAMX;IACR,KACAI,IAAIE,OAAO,CAACM,MAAM,CAAC;QACjBC,YAAYjB;QACZC;QACAC;QACAG,IAAIA;QACJC;QACAC;QACAC;IACF;IAEJ,OAAOK;AACT,EAAE"}
|
package/dist/types.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["import type { GeneratedTypes } from 'payload';\
|
1
|
+
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["import type { GeneratedTypes } from 'payload';\n\nimport type { TranslateResolver } from './resolvers/types';\n\nexport type TranslatorConfig = {\n /**\n * Collections with the enabled translator in the admin UI\n */\n collections: (keyof GeneratedTypes['collections'])[];\n /**\n * Disable the plugin\n */\n disabled?: boolean;\n /**\n * Globals with the enabled translator in the admin UI\n */\n globals: (keyof GeneratedTypes['globals'])[];\n /**\n * Add resolvers that you want to include, examples on how to write your own in ./plugin/src/resolvers\n */\n resolvers: TranslateResolver[];\n};\n"],"names":[],"rangeMappings":"","mappings":"AAIA,WAiBE"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../src/utils/chunkArray.ts"],"sourcesContent":["export const chunkArray = <T>(array: T[], length: number): T[][] => {\
|
1
|
+
{"version":3,"sources":["../../src/utils/chunkArray.ts"],"sourcesContent":["export const chunkArray = <T>(array: T[], length: number): T[][] => {\n return Array.from({ length: Math.ceil(array.length / length) }, (_, i) =>\n array.slice(i * length, i * length + length),\n );\n};\n"],"names":["chunkArray","array","length","Array","from","Math","ceil","_","i","slice"],"rangeMappings":";;;;","mappings":"AAAA,OAAO,MAAMA,aAAa,CAAIC,OAAYC;IACxC,OAAOC,MAAMC,IAAI,CAAC;QAAEF,QAAQG,KAAKC,IAAI,CAACL,MAAMC,MAAM,GAAGA;IAAQ,GAAG,CAACK,GAAGC,IAClEP,MAAMQ,KAAK,CAACD,IAAIN,QAAQM,IAAIN,SAASA;AAEzC,EAAE"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../src/utils/isEmpty.ts"],"sourcesContent":["export const isEmpty = (value: unknown) => {\
|
1
|
+
{"version":3,"sources":["../../src/utils/isEmpty.ts"],"sourcesContent":["export const isEmpty = (value: unknown) => {\n if (Array.isArray(value)) return value.length === 0;\n if (value === null || typeof value === 'undefined') return true;\n if (typeof value === 'object' && Object.keys(value).length === 0) return true;\n\n return false;\n};\n"],"names":["isEmpty","value","Array","isArray","length","Object","keys"],"rangeMappings":";;;;;","mappings":"AAAA,OAAO,MAAMA,UAAU,CAACC;IACtB,IAAIC,MAAMC,OAAO,CAACF,QAAQ,OAAOA,MAAMG,MAAM,KAAK;IAClD,IAAIH,UAAU,QAAQ,OAAOA,UAAU,aAAa,OAAO;IAC3D,IAAI,OAAOA,UAAU,YAAYI,OAAOC,IAAI,CAACL,OAAOG,MAAM,KAAK,GAAG,OAAO;IAEzE,OAAO;AACT,EAAE"}
|
package/package.json
CHANGED
@@ -1,21 +1,21 @@
|
|
1
1
|
{
|
2
2
|
"name": "@payload-enchants/translator",
|
3
3
|
"private": false,
|
4
|
-
"version": "1.1.
|
4
|
+
"version": "1.1.9",
|
5
5
|
"repository": "https://github.com/r1tsuu/payload-enchants",
|
6
6
|
"author": "r1tsuu",
|
7
7
|
"bugs": "https://github.com/r1tsuu/payload-enchants/issues",
|
8
8
|
"type": "module",
|
9
9
|
"peerDependencies": {
|
10
|
-
"@payloadcms/translations": "^3.0.0-beta.
|
11
|
-
"@payloadcms/ui": "^3.0.0-beta.
|
12
|
-
"payload": "^3.0.0-beta.
|
10
|
+
"@payloadcms/translations": "^3.0.0-beta.25",
|
11
|
+
"@payloadcms/ui": "^3.0.0-beta.25",
|
12
|
+
"payload": "^3.0.0-beta.25"
|
13
13
|
},
|
14
14
|
"devDependencies": {
|
15
|
-
"@payloadcms/translations": "3.0.0-beta.
|
16
|
-
"@payloadcms/ui": "3.0.0-beta.
|
15
|
+
"@payloadcms/translations": "3.0.0-beta.25",
|
16
|
+
"@payloadcms/ui": "3.0.0-beta.25",
|
17
17
|
"@types/react": "18.2.64",
|
18
|
-
"payload": "3.0.0-beta.
|
18
|
+
"payload": "3.0.0-beta.25",
|
19
19
|
"react": "18.2.0",
|
20
20
|
"typescript": "^5.4.2"
|
21
21
|
},
|