@roxxel/payload-multilang 0.0.5 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -3
- package/dist/components/LanguageListToolbar.js +4 -3
- package/dist/components/LanguageListToolbar.js.map +1 -1
- package/dist/components/LanguageMetabox.js +18 -17
- package/dist/components/LanguageMetabox.js.map +1 -1
- package/dist/components/TranslationActionsClient.js +16 -14
- package/dist/components/TranslationActionsClient.js.map +1 -1
- package/dist/components/TranslationColumnCell.js +4 -1
- package/dist/components/TranslationColumnCell.js.map +1 -1
- package/dist/components/TranslationColumnCellClient.js +16 -7
- package/dist/components/TranslationColumnCellClient.js.map +1 -1
- package/dist/components/TranslationsTab.js +9 -8
- package/dist/components/TranslationsTab.js.map +1 -1
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +1 -1
- package/dist/constants.js.map +1 -1
- package/dist/endpoints/translations.js +4 -6
- package/dist/endpoints/translations.js.map +1 -1
- package/dist/hooks/translatedCollection.d.ts +2 -1
- package/dist/hooks/translatedCollection.js +122 -15
- package/dist/hooks/translatedCollection.js.map +1 -1
- package/dist/hooks/translatedGlobal.js +5 -1
- package/dist/hooks/translatedGlobal.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +22 -2
- package/dist/index.js.map +1 -1
- package/dist/lib/config.js +2 -10
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/data.d.ts +1 -2
- package/dist/lib/data.js +32 -4
- package/dist/lib/data.js.map +1 -1
- package/dist/translations.d.ts +72 -0
- package/dist/translations.js +72 -0
- package/dist/translations.js.map +1 -0
- package/dist/types.d.ts +0 -19
- package/dist/types.js.map +1 -1
- package/docs/configuration.md +43 -9
- package/docs/usage.md +10 -34
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -23,9 +23,7 @@ export default buildConfig({
|
|
|
23
23
|
plugins: [
|
|
24
24
|
payloadMultilang({
|
|
25
25
|
collections: {
|
|
26
|
-
posts:
|
|
27
|
-
synchronizedFields: ['featuredImage', 'author'],
|
|
28
|
-
},
|
|
26
|
+
posts: true,
|
|
29
27
|
},
|
|
30
28
|
globals: {
|
|
31
29
|
'site-settings': {
|
|
@@ -54,6 +52,21 @@ export default buildConfig({
|
|
|
54
52
|
})
|
|
55
53
|
```
|
|
56
54
|
|
|
55
|
+
Mark shared fields in the collection field config:
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
{
|
|
59
|
+
name: 'featuredImage',
|
|
60
|
+
type: 'upload',
|
|
61
|
+
relationTo: 'media',
|
|
62
|
+
custom: {
|
|
63
|
+
multilang: {
|
|
64
|
+
synchronize: true,
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
57
70
|
In the Payload admin panel, enabled collections get:
|
|
58
71
|
|
|
59
72
|
- a language selector in the document sidebar
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { useConfig, useRouteTransition } from '@payloadcms/ui';
|
|
3
|
+
import { useConfig, useRouteTransition, useTranslation } from '@payloadcms/ui';
|
|
4
4
|
import { usePathname, useRouter, useSearchParams } from 'next/navigation.js';
|
|
5
5
|
import { useMemo } from 'react';
|
|
6
6
|
import '../styles/admin.css';
|
|
@@ -11,6 +11,7 @@ export const LanguageListToolbar = ({ collectionSlug })=>{
|
|
|
11
11
|
const router = useRouter();
|
|
12
12
|
const searchParams = useSearchParams();
|
|
13
13
|
const { isTransitioning, startRouteTransition } = useRouteTransition();
|
|
14
|
+
const { t } = useTranslation();
|
|
14
15
|
const languages = getConfiguredLanguagesFromConfig(config);
|
|
15
16
|
const fieldNames = useMemo(()=>getCollectionFieldNames({
|
|
16
17
|
collectionSlug,
|
|
@@ -44,14 +45,14 @@ export const LanguageListToolbar = ({ collectionSlug })=>{
|
|
|
44
45
|
children: /*#__PURE__*/ _jsx("label", {
|
|
45
46
|
className: "payload-multilang-toolbar__select",
|
|
46
47
|
children: /*#__PURE__*/ _jsxs("select", {
|
|
47
|
-
"aria-label":
|
|
48
|
+
"aria-label": t('payloadMultilang:language'),
|
|
48
49
|
disabled: isTransitioning,
|
|
49
50
|
onChange: (event)=>handleLanguageChange(event.target.value),
|
|
50
51
|
value: currentLanguage,
|
|
51
52
|
children: [
|
|
52
53
|
/*#__PURE__*/ _jsx("option", {
|
|
53
54
|
value: "",
|
|
54
|
-
children:
|
|
55
|
+
children: t('payloadMultilang:allLanguages')
|
|
55
56
|
}),
|
|
56
57
|
languages.map((language)=>/*#__PURE__*/ _jsxs("option", {
|
|
57
58
|
value: language.code,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/LanguageListToolbar.tsx"],"sourcesContent":["'use client'\n\nimport { useConfig, useRouteTransition } from '@payloadcms/ui'\nimport { usePathname, useRouter, useSearchParams } from 'next/navigation.js'\nimport { useMemo } from 'react'\n\nimport '../styles/admin.css'\nimport { getCollectionFieldNames, getConfiguredLanguagesFromConfig } from './config.js'\n\ntype Props = {\n collectionSlug: string\n}\n\nexport const LanguageListToolbar = ({ collectionSlug }: Props) => {\n const { config } = useConfig()\n const pathname = usePathname()\n const router = useRouter()\n const searchParams = useSearchParams()\n const { isTransitioning, startRouteTransition } = useRouteTransition()\n const languages = getConfiguredLanguagesFromConfig(config)\n const fieldNames = useMemo(\n () => getCollectionFieldNames({ collectionSlug, config }),\n [collectionSlug, config],\n )\n const languageParam = `where[${fieldNames.language}][equals]`\n const currentLanguage = searchParams.get(languageParam) || ''\n\n if (!languages.length) {\n return null\n }\n\n const handleLanguageChange = (language: string) => {\n const nextParams = new URLSearchParams(searchParams.toString())\n\n if (language) {\n nextParams.set(languageParam, language)\n } else {\n nextParams.delete(languageParam)\n }\n\n nextParams.set('page', '1')\n\n const query = nextParams.toString()\n const href = query ? `${pathname}?${query}` : pathname\n\n startRouteTransition(() => {\n router.push(href)\n })\n }\n\n return (\n <div className=\"payload-multilang-toolbar\" data-testid=\"multilang-list-toolbar\">\n <label className=\"payload-multilang-toolbar__select\">\n <select\n aria-label
|
|
1
|
+
{"version":3,"sources":["../../src/components/LanguageListToolbar.tsx"],"sourcesContent":["'use client'\n\nimport { useConfig, useRouteTransition, useTranslation } from '@payloadcms/ui'\nimport { usePathname, useRouter, useSearchParams } from 'next/navigation.js'\nimport { useMemo } from 'react'\n\nimport '../styles/admin.css'\n\nimport type {\n PayloadMultilangTranslationKey,\n PayloadMultilangTranslations,\n} from '../translations.js'\n\nimport { getCollectionFieldNames, getConfiguredLanguagesFromConfig } from './config.js'\n\ntype Props = {\n collectionSlug: string\n}\n\nexport const LanguageListToolbar = ({ collectionSlug }: Props) => {\n const { config } = useConfig()\n const pathname = usePathname()\n const router = useRouter()\n const searchParams = useSearchParams()\n const { isTransitioning, startRouteTransition } = useRouteTransition()\n const { t } = useTranslation<\n PayloadMultilangTranslations,\n PayloadMultilangTranslationKey\n >()\n const languages = getConfiguredLanguagesFromConfig(config)\n const fieldNames = useMemo(\n () => getCollectionFieldNames({ collectionSlug, config }),\n [collectionSlug, config],\n )\n const languageParam = `where[${fieldNames.language}][equals]`\n const currentLanguage = searchParams.get(languageParam) || ''\n\n if (!languages.length) {\n return null\n }\n\n const handleLanguageChange = (language: string) => {\n const nextParams = new URLSearchParams(searchParams.toString())\n\n if (language) {\n nextParams.set(languageParam, language)\n } else {\n nextParams.delete(languageParam)\n }\n\n nextParams.set('page', '1')\n\n const query = nextParams.toString()\n const href = query ? `${pathname}?${query}` : pathname\n\n startRouteTransition(() => {\n router.push(href)\n })\n }\n\n return (\n <div className=\"payload-multilang-toolbar\" data-testid=\"multilang-list-toolbar\">\n <label className=\"payload-multilang-toolbar__select\">\n <select\n aria-label={t('payloadMultilang:language')}\n disabled={isTransitioning}\n onChange={(event) => handleLanguageChange(event.target.value)}\n value={currentLanguage}\n >\n <option value=\"\">{t('payloadMultilang:allLanguages')}</option>\n {languages.map((language) => (\n <option key={language.code} value={language.code}>\n {language.flagLabel ? `${language.flagLabel} ` : ''}\n {language.name}\n </option>\n ))}\n </select>\n </label>\n </div>\n )\n}\n"],"names":["useConfig","useRouteTransition","useTranslation","usePathname","useRouter","useSearchParams","useMemo","getCollectionFieldNames","getConfiguredLanguagesFromConfig","LanguageListToolbar","collectionSlug","config","pathname","router","searchParams","isTransitioning","startRouteTransition","t","languages","fieldNames","languageParam","language","currentLanguage","get","length","handleLanguageChange","nextParams","URLSearchParams","toString","set","delete","query","href","push","div","className","data-testid","label","select","aria-label","disabled","onChange","event","target","value","option","map","code","flagLabel","name"],"mappings":"AAAA;;AAEA,SAASA,SAAS,EAAEC,kBAAkB,EAAEC,cAAc,QAAQ,iBAAgB;AAC9E,SAASC,WAAW,EAAEC,SAAS,EAAEC,eAAe,QAAQ,qBAAoB;AAC5E,SAASC,OAAO,QAAQ,QAAO;AAE/B,OAAO,sBAAqB;AAO5B,SAASC,uBAAuB,EAAEC,gCAAgC,QAAQ,cAAa;AAMvF,OAAO,MAAMC,sBAAsB,CAAC,EAAEC,cAAc,EAAS;IAC3D,MAAM,EAAEC,MAAM,EAAE,GAAGX;IACnB,MAAMY,WAAWT;IACjB,MAAMU,SAAST;IACf,MAAMU,eAAeT;IACrB,MAAM,EAAEU,eAAe,EAAEC,oBAAoB,EAAE,GAAGf;IAClD,MAAM,EAAEgB,CAAC,EAAE,GAAGf;IAId,MAAMgB,YAAYV,iCAAiCG;IACnD,MAAMQ,aAAab,QACjB,IAAMC,wBAAwB;YAAEG;YAAgBC;QAAO,IACvD;QAACD;QAAgBC;KAAO;IAE1B,MAAMS,gBAAgB,CAAC,MAAM,EAAED,WAAWE,QAAQ,CAAC,SAAS,CAAC;IAC7D,MAAMC,kBAAkBR,aAAaS,GAAG,CAACH,kBAAkB;IAE3D,IAAI,CAACF,UAAUM,MAAM,EAAE;QACrB,OAAO;IACT;IAEA,MAAMC,uBAAuB,CAACJ;QAC5B,MAAMK,aAAa,IAAIC,gBAAgBb,aAAac,QAAQ;QAE5D,IAAIP,UAAU;YACZK,WAAWG,GAAG,CAACT,eAAeC;QAChC,OAAO;YACLK,WAAWI,MAAM,CAACV;QACpB;QAEAM,WAAWG,GAAG,CAAC,QAAQ;QAEvB,MAAME,QAAQL,WAAWE,QAAQ;QACjC,MAAMI,OAAOD,QAAQ,GAAGnB,SAAS,CAAC,EAAEmB,OAAO,GAAGnB;QAE9CI,qBAAqB;YACnBH,OAAOoB,IAAI,CAACD;QACd;IACF;IAEA,qBACE,KAACE;QAAIC,WAAU;QAA4BC,eAAY;kBACrD,cAAA,KAACC;YAAMF,WAAU;sBACf,cAAA,MAACG;gBACCC,cAAYtB,EAAE;gBACduB,UAAUzB;gBACV0B,UAAU,CAACC,QAAUjB,qBAAqBiB,MAAMC,MAAM,CAACC,KAAK;gBAC5DA,OAAOtB;;kCAEP,KAACuB;wBAAOD,OAAM;kCAAI3B,EAAE;;oBACnBC,UAAU4B,GAAG,CAAC,CAACzB,yBACd,MAACwB;4BAA2BD,OAAOvB,SAAS0B,IAAI;;gCAC7C1B,SAAS2B,SAAS,GAAG,GAAG3B,SAAS2B,SAAS,CAAC,CAAC,CAAC,GAAG;gCAChD3B,SAAS4B,IAAI;;2BAFH5B,SAAS0B,IAAI;;;;;AAStC,EAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { toast, useConfig, useDocumentInfo, useField, useRouteTransition } from '@payloadcms/ui';
|
|
3
|
+
import { toast, useConfig, useDocumentInfo, useField, useRouteTransition, useTranslation } from '@payloadcms/ui';
|
|
4
4
|
import { useRouter } from 'next/navigation.js';
|
|
5
5
|
import { formatAdminURL } from 'payload/shared';
|
|
6
6
|
import { useEffect, useMemo, useState } from 'react';
|
|
@@ -29,16 +29,13 @@ const PenIcon = ()=>/*#__PURE__*/ _jsxs("svg", {
|
|
|
29
29
|
})
|
|
30
30
|
]
|
|
31
31
|
});
|
|
32
|
-
const getDocumentID = (doc)=>{
|
|
33
|
-
const id = doc?.id;
|
|
34
|
-
return typeof id === 'number' || typeof id === 'string' ? id : undefined;
|
|
35
|
-
};
|
|
36
32
|
const isSameDocumentID = (left, right)=>left !== undefined && right !== undefined && String(left) === String(right);
|
|
37
33
|
export const LanguageMetabox = ()=>{
|
|
38
34
|
const { config } = useConfig();
|
|
39
|
-
const {
|
|
35
|
+
const { id, collectionSlug } = useDocumentInfo();
|
|
40
36
|
const router = useRouter();
|
|
41
37
|
const { isTransitioning, startRouteTransition } = useRouteTransition();
|
|
38
|
+
const { t } = useTranslation();
|
|
42
39
|
const fieldNames = useMemo(()=>getCollectionFieldNames({
|
|
43
40
|
collectionSlug,
|
|
44
41
|
config
|
|
@@ -134,7 +131,7 @@ export const LanguageMetabox = ()=>{
|
|
|
134
131
|
};
|
|
135
132
|
const createTranslation = async (targetLanguage)=>{
|
|
136
133
|
if (!collectionSlug || !docID) {
|
|
137
|
-
toast.error('
|
|
134
|
+
toast.error(t('payloadMultilang:saveBeforeCreatingTranslations'));
|
|
138
135
|
return;
|
|
139
136
|
}
|
|
140
137
|
setBusyLanguage(targetLanguage);
|
|
@@ -155,7 +152,7 @@ export const LanguageMetabox = ()=>{
|
|
|
155
152
|
setBusyLanguage(undefined);
|
|
156
153
|
if (!response.ok) {
|
|
157
154
|
const result = await response.json().catch(()=>undefined);
|
|
158
|
-
toast.error(result?.message || '
|
|
155
|
+
toast.error(result?.message || t('payloadMultilang:translationCouldNotBeCreated'));
|
|
159
156
|
return;
|
|
160
157
|
}
|
|
161
158
|
const result = await response.json();
|
|
@@ -171,14 +168,14 @@ export const LanguageMetabox = ()=>{
|
|
|
171
168
|
/*#__PURE__*/ _jsx("div", {
|
|
172
169
|
className: "payload-multilang-metabox__header",
|
|
173
170
|
children: /*#__PURE__*/ _jsx("h3", {
|
|
174
|
-
children:
|
|
171
|
+
children: t('payloadMultilang:language')
|
|
175
172
|
})
|
|
176
173
|
}),
|
|
177
174
|
/*#__PURE__*/ _jsxs("label", {
|
|
178
175
|
className: "payload-multilang-field",
|
|
179
176
|
children: [
|
|
180
177
|
/*#__PURE__*/ _jsx("span", {
|
|
181
|
-
children:
|
|
178
|
+
children: t('payloadMultilang:language')
|
|
182
179
|
}),
|
|
183
180
|
/*#__PURE__*/ _jsxs("div", {
|
|
184
181
|
className: "payload-multilang-language-select",
|
|
@@ -194,7 +191,7 @@ export const LanguageMetabox = ()=>{
|
|
|
194
191
|
children: [
|
|
195
192
|
/*#__PURE__*/ _jsx("option", {
|
|
196
193
|
value: "",
|
|
197
|
-
children:
|
|
194
|
+
children: t('payloadMultilang:unassigned')
|
|
198
195
|
}),
|
|
199
196
|
languages.map((language)=>{
|
|
200
197
|
const isCurrent = selectedLanguageCode === language.code;
|
|
@@ -220,7 +217,7 @@ export const LanguageMetabox = ()=>{
|
|
|
220
217
|
"data-testid": "multilang-sidebar-translations",
|
|
221
218
|
children: [
|
|
222
219
|
/*#__PURE__*/ _jsx("h4", {
|
|
223
|
-
children:
|
|
220
|
+
children: t('payloadMultilang:translations')
|
|
224
221
|
}),
|
|
225
222
|
languages.map((language)=>{
|
|
226
223
|
const translation = translationState?.translations[language.code];
|
|
@@ -240,19 +237,23 @@ export const LanguageMetabox = ()=>{
|
|
|
240
237
|
}),
|
|
241
238
|
isCurrent ? /*#__PURE__*/ _jsx("span", {
|
|
242
239
|
className: "payload-multilang-translation-row__current",
|
|
243
|
-
children:
|
|
240
|
+
children: t('payloadMultilang:current')
|
|
244
241
|
}) : isUnavailableForCreate ? /*#__PURE__*/ _jsx("span", {
|
|
245
242
|
className: "payload-multilang-translation-row__current",
|
|
246
|
-
children:
|
|
243
|
+
children: t('payloadMultilang:localized')
|
|
247
244
|
}) : translationID ? /*#__PURE__*/ _jsx("button", {
|
|
248
|
-
"aria-label":
|
|
245
|
+
"aria-label": t('payloadMultilang:editTranslationFor', {
|
|
246
|
+
language: language.name
|
|
247
|
+
}),
|
|
249
248
|
className: "payload-multilang-link-button",
|
|
250
249
|
disabled: isTransitioning,
|
|
251
250
|
onClick: ()=>navigateToTranslation(translationID),
|
|
252
251
|
type: "button",
|
|
253
252
|
children: /*#__PURE__*/ _jsx(PenIcon, {})
|
|
254
253
|
}) : /*#__PURE__*/ _jsx("button", {
|
|
255
|
-
"aria-label":
|
|
254
|
+
"aria-label": t('payloadMultilang:createTranslationFor', {
|
|
255
|
+
language: language.name
|
|
256
|
+
}),
|
|
256
257
|
className: "payload-multilang-icon-button",
|
|
257
258
|
disabled: !docID || busyLanguage === language.code || isTransitioning,
|
|
258
259
|
onClick: ()=>void createTranslation(language.code),
|
|
@@ -264,7 +265,7 @@ export const LanguageMetabox = ()=>{
|
|
|
264
265
|
}),
|
|
265
266
|
!docID ? /*#__PURE__*/ _jsx("div", {
|
|
266
267
|
className: "payload-multilang-muted",
|
|
267
|
-
children:
|
|
268
|
+
children: t('payloadMultilang:saveBeforeAddingTranslations')
|
|
268
269
|
}) : null
|
|
269
270
|
]
|
|
270
271
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/LanguageMetabox.tsx"],"sourcesContent":["'use client'\n\nimport { toast, useConfig, useDocumentInfo, useField, useRouteTransition } from '@payloadcms/ui'\nimport { useRouter } from 'next/navigation.js'\nimport { formatAdminURL } from 'payload/shared'\nimport { useEffect, useMemo, useState } from 'react'\n\nimport '../styles/admin.css'\nimport type { TranslationState } from '../types.js'\nimport {\n getCollectionFieldNames,\n getConfiguredLanguagesFromConfig,\n getDefaultLanguageFromConfig,\n} from './config.js'\n\nconst PenIcon = () => (\n <svg\n aria-hidden=\"true\"\n className=\"payload-multilang-pen-icon\"\n fill=\"none\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n width=\"16\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M9.9 2.6 13.4 6 5.7 13.7 2.2 14.4 2.9 10.9 9.9 2.6Z\"\n stroke=\"currentColor\"\n strokeLinejoin=\"round\"\n strokeWidth=\"1.4\"\n />\n <path d=\"M8.8 3.9 12.1 7.2\" stroke=\"currentColor\" strokeLinecap=\"round\" strokeWidth=\"1.4\" />\n </svg>\n)\n\nconst getDocumentID = (doc: Record<string, unknown> | undefined): number | string | undefined => {\n const id = doc?.id\n\n return typeof id === 'number' || typeof id === 'string' ? id : undefined\n}\n\nconst isSameDocumentID = (\n left: number | string | undefined,\n right: number | string | undefined,\n): boolean => left !== undefined && right !== undefined && String(left) === String(right)\n\nexport const LanguageMetabox = () => {\n const { config } = useConfig()\n const { collectionSlug, id } = useDocumentInfo()\n const router = useRouter()\n const { isTransitioning, startRouteTransition } = useRouteTransition()\n const fieldNames = useMemo(\n () => getCollectionFieldNames({ collectionSlug, config }),\n [collectionSlug, config],\n )\n const languageField = useField<string>({ path: fieldNames.language })\n const languages = getConfiguredLanguagesFromConfig(config)\n const defaultLanguage = getDefaultLanguageFromConfig(config)\n const [busyLanguage, setBusyLanguage] = useState<string>()\n const [translationState, setTranslationState] = useState<TranslationState>()\n const groupField = useField<string>({ path: fieldNames.group })\n const docID = typeof id === 'number' || typeof id === 'string' ? id : undefined\n const groupValue = groupField.value\n const isCreation = !docID\n const localizedLanguageCodes = useMemo(\n () => new Set(Object.keys(translationState?.translations || {})),\n [translationState?.translations],\n )\n const configuredLanguageCodes = useMemo(\n () => new Set(languages.map((language) => language.code)),\n [languages],\n )\n const availableCreationLanguage = useMemo(\n () => languages.find((language) => !localizedLanguageCodes.has(language.code)),\n [languages, localizedLanguageCodes],\n )\n const preferredCreationLanguage =\n (defaultLanguage && !localizedLanguageCodes.has(defaultLanguage.code)\n ? defaultLanguage\n : availableCreationLanguage\n )?.code || ''\n\n useEffect(() => {\n if (isCreation) {\n if (!preferredCreationLanguage) {\n if (languageField.value && localizedLanguageCodes.has(languageField.value)) {\n languageField.setValue('')\n }\n\n return\n }\n\n if (!languageField.value || localizedLanguageCodes.has(languageField.value)) {\n languageField.setValue(preferredCreationLanguage)\n }\n\n return\n }\n\n if (\n languageField.value &&\n !configuredLanguageCodes.has(languageField.value)\n ) {\n languageField.setValue('')\n }\n }, [\n configuredLanguageCodes,\n isCreation,\n languageField,\n localizedLanguageCodes,\n preferredCreationLanguage,\n ])\n\n useEffect(() => {\n if (!collectionSlug || (!docID && !groupValue)) {\n setTranslationState(undefined)\n return\n }\n\n const loadState = async () => {\n const query = docID\n ? `id=${encodeURIComponent(String(docID))}`\n : `group=${encodeURIComponent(groupValue!)}`\n\n const response = await fetch(\n formatAdminURL({\n apiRoute: config.routes.api,\n path: `/${collectionSlug}/multilang/state?${query}`,\n }),\n {\n credentials: 'include',\n },\n )\n\n if (!response.ok) {\n return\n }\n\n const result = (await response.json()) as TranslationState\n setTranslationState(result)\n }\n\n void loadState()\n }, [collectionSlug, config.routes.api, docID, groupValue])\n\n const selectedLanguageCode = isCreation\n ? languageField.value || preferredCreationLanguage\n : languageField.value && configuredLanguageCodes.has(languageField.value)\n ? languageField.value\n : ''\n const selectedLanguage = languages.find((language) => language.code === selectedLanguageCode)\n const persistedLanguage = !isCreation ? translationState?.language : undefined\n const hasAssignedConfiguredLanguage = Boolean(\n !isCreation &&\n (translationState\n ? persistedLanguage && configuredLanguageCodes.has(persistedLanguage)\n : selectedLanguage),\n )\n\n const collectionAdminURL = (documentID: number | string) =>\n formatAdminURL({\n adminRoute: config.routes.admin,\n path: `/collections/${collectionSlug}/${documentID}`,\n })\n\n const navigateToTranslation = (documentID: number | string) => {\n startRouteTransition(() => {\n router.push(collectionAdminURL(documentID))\n })\n }\n\n const createTranslation = async (targetLanguage: string) => {\n if (!collectionSlug || !docID) {\n toast.error('Save the document before creating translations.')\n return\n }\n\n setBusyLanguage(targetLanguage)\n\n const response = await fetch(\n formatAdminURL({\n apiRoute: config.routes.api,\n path: `/${collectionSlug}/multilang/create`,\n }),\n {\n body: JSON.stringify({\n sourceId: docID,\n targetLanguage,\n }),\n credentials: 'include',\n headers: {\n 'Content-Type': 'application/json',\n },\n method: 'POST',\n },\n )\n\n setBusyLanguage(undefined)\n\n if (!response.ok) {\n const result = (await response.json().catch(() => undefined)) as\n { message?: string } | undefined\n toast.error(result?.message || 'Translation could not be created.')\n return\n }\n\n const result = (await response.json()) as {\n doc?: { id?: number | string }\n }\n\n if (result.doc?.id) {\n startRouteTransition(() => {\n router.push(collectionAdminURL(result.doc!.id!))\n })\n }\n }\n\n return (\n <section className=\"payload-multilang-metabox\">\n <div className=\"payload-multilang-metabox__header\">\n <h3>Language</h3>\n </div>\n\n <label className=\"payload-multilang-field\">\n <span>Language</span>\n <div className=\"payload-multilang-language-select\">\n <span className=\"payload-multilang-language-select__flag\">\n {selectedLanguage?.flagLabel || '--'}\n </span>\n <select\n disabled={hasAssignedConfiguredLanguage}\n onChange={(event) => languageField.setValue(event.target.value)}\n value={selectedLanguageCode}\n >\n <option value=\"\">Unassigned</option>\n {languages.map((language) => {\n const isCurrent = selectedLanguageCode === language.code\n const isLocalized = localizedLanguageCodes.has(language.code)\n const disabled =\n isCreation || !hasAssignedConfiguredLanguage\n ? isLocalized && !isCurrent\n : true\n\n return (\n <option disabled={disabled} key={language.code} value={language.code}>\n {language.flagLabel ? `${language.flagLabel} ` : ''}\n {language.name}\n </option>\n )\n })}\n </select>\n </div>\n </label>\n\n <div className=\"payload-multilang-translations\" data-testid=\"multilang-sidebar-translations\">\n <h4>Translations</h4>\n {languages.map((language) => {\n const translation = translationState?.translations[language.code]\n const translationID =\n typeof translation?.id === 'number' || typeof translation?.id === 'string'\n ? translation.id\n : undefined\n const isCurrent = isSameDocumentID(translationID, docID)\n const isUnavailableForCreate =\n isCreation && Boolean(translationID) && selectedLanguageCode !== language.code\n\n return (\n <div className=\"payload-multilang-translation-row\" key={language.code}>\n <span className=\"payload-multilang-translation-row__flag\">\n {language.flagLabel || language.code.toUpperCase()}\n </span>\n <span className=\"payload-multilang-translation-row__name\">{language.name}</span>\n {isCurrent ? (\n <span className=\"payload-multilang-translation-row__current\">Current</span>\n ) : isUnavailableForCreate ? (\n <span className=\"payload-multilang-translation-row__current\">Localized</span>\n ) : translationID ? (\n <button\n aria-label={`Edit ${language.name} translation`}\n className=\"payload-multilang-link-button\"\n disabled={isTransitioning}\n onClick={() => navigateToTranslation(translationID)}\n type=\"button\"\n >\n <PenIcon />\n </button>\n ) : (\n <button\n aria-label={`Create ${language.name} translation`}\n className=\"payload-multilang-icon-button\"\n disabled={!docID || busyLanguage === language.code || isTransitioning}\n onClick={() => void createTranslation(language.code)}\n type=\"button\"\n >\n +\n </button>\n )}\n </div>\n )\n })}\n {!docID ? (\n <div className=\"payload-multilang-muted\">Save before adding translations.</div>\n ) : null}\n </div>\n </section>\n )\n}\n"],"names":["toast","useConfig","useDocumentInfo","useField","useRouteTransition","useRouter","formatAdminURL","useEffect","useMemo","useState","getCollectionFieldNames","getConfiguredLanguagesFromConfig","getDefaultLanguageFromConfig","PenIcon","svg","aria-hidden","className","fill","height","viewBox","width","xmlns","path","d","stroke","strokeLinejoin","strokeWidth","strokeLinecap","getDocumentID","doc","id","undefined","isSameDocumentID","left","right","String","LanguageMetabox","config","collectionSlug","router","isTransitioning","startRouteTransition","fieldNames","languageField","language","languages","defaultLanguage","busyLanguage","setBusyLanguage","translationState","setTranslationState","groupField","group","docID","groupValue","value","isCreation","localizedLanguageCodes","Set","Object","keys","translations","configuredLanguageCodes","map","code","availableCreationLanguage","find","has","preferredCreationLanguage","setValue","loadState","query","encodeURIComponent","response","fetch","apiRoute","routes","api","credentials","ok","result","json","selectedLanguageCode","selectedLanguage","persistedLanguage","hasAssignedConfiguredLanguage","Boolean","collectionAdminURL","documentID","adminRoute","admin","navigateToTranslation","push","createTranslation","targetLanguage","error","body","JSON","stringify","sourceId","headers","method","catch","message","section","div","h3","label","span","flagLabel","select","disabled","onChange","event","target","option","isCurrent","isLocalized","name","data-testid","h4","translation","translationID","isUnavailableForCreate","toUpperCase","button","aria-label","onClick","type"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/components/LanguageMetabox.tsx"],"sourcesContent":["'use client'\n\nimport {\n toast,\n useConfig,\n useDocumentInfo,\n useField,\n useRouteTransition,\n useTranslation,\n} from '@payloadcms/ui'\nimport { useRouter } from 'next/navigation.js'\nimport { formatAdminURL } from 'payload/shared'\nimport { useEffect, useMemo, useState } from 'react'\n\nimport '../styles/admin.css'\n\nimport type {\n PayloadMultilangTranslationKey,\n PayloadMultilangTranslations,\n} from '../translations.js'\nimport type { TranslationState } from '../types.js'\n\nimport {\n getCollectionFieldNames,\n getConfiguredLanguagesFromConfig,\n getDefaultLanguageFromConfig,\n} from './config.js'\n\nconst PenIcon = () => (\n <svg\n aria-hidden=\"true\"\n className=\"payload-multilang-pen-icon\"\n fill=\"none\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n width=\"16\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M9.9 2.6 13.4 6 5.7 13.7 2.2 14.4 2.9 10.9 9.9 2.6Z\"\n stroke=\"currentColor\"\n strokeLinejoin=\"round\"\n strokeWidth=\"1.4\"\n />\n <path d=\"M8.8 3.9 12.1 7.2\" stroke=\"currentColor\" strokeLinecap=\"round\" strokeWidth=\"1.4\" />\n </svg>\n)\n\nconst isSameDocumentID = (\n left: number | string | undefined,\n right: number | string | undefined,\n): boolean => left !== undefined && right !== undefined && String(left) === String(right)\n\nexport const LanguageMetabox = () => {\n const { config } = useConfig()\n const { id, collectionSlug } = useDocumentInfo()\n const router = useRouter()\n const { isTransitioning, startRouteTransition } = useRouteTransition()\n const { t } = useTranslation<\n PayloadMultilangTranslations,\n PayloadMultilangTranslationKey\n >()\n const fieldNames = useMemo(\n () => getCollectionFieldNames({ collectionSlug, config }),\n [collectionSlug, config],\n )\n const languageField = useField<string>({ path: fieldNames.language })\n const languages = getConfiguredLanguagesFromConfig(config)\n const defaultLanguage = getDefaultLanguageFromConfig(config)\n const [busyLanguage, setBusyLanguage] = useState<string>()\n const [translationState, setTranslationState] = useState<TranslationState>()\n const groupField = useField<string>({ path: fieldNames.group })\n const docID = typeof id === 'number' || typeof id === 'string' ? id : undefined\n const groupValue = groupField.value\n const isCreation = !docID\n const localizedLanguageCodes = useMemo(\n () => new Set(Object.keys(translationState?.translations || {})),\n [translationState?.translations],\n )\n const configuredLanguageCodes = useMemo(\n () => new Set(languages.map((language) => language.code)),\n [languages],\n )\n const availableCreationLanguage = useMemo(\n () => languages.find((language) => !localizedLanguageCodes.has(language.code)),\n [languages, localizedLanguageCodes],\n )\n const preferredCreationLanguage =\n (defaultLanguage && !localizedLanguageCodes.has(defaultLanguage.code)\n ? defaultLanguage\n : availableCreationLanguage\n )?.code || ''\n\n useEffect(() => {\n if (isCreation) {\n if (!preferredCreationLanguage) {\n if (languageField.value && localizedLanguageCodes.has(languageField.value)) {\n languageField.setValue('')\n }\n\n return\n }\n\n if (!languageField.value || localizedLanguageCodes.has(languageField.value)) {\n languageField.setValue(preferredCreationLanguage)\n }\n\n return\n }\n\n if (\n languageField.value &&\n !configuredLanguageCodes.has(languageField.value)\n ) {\n languageField.setValue('')\n }\n }, [\n configuredLanguageCodes,\n isCreation,\n languageField,\n localizedLanguageCodes,\n preferredCreationLanguage,\n ])\n\n useEffect(() => {\n if (!collectionSlug || (!docID && !groupValue)) {\n setTranslationState(undefined)\n return\n }\n\n const loadState = async () => {\n const query = docID\n ? `id=${encodeURIComponent(String(docID))}`\n : `group=${encodeURIComponent(groupValue)}`\n\n const response = await fetch(\n formatAdminURL({\n apiRoute: config.routes.api,\n path: `/${collectionSlug}/multilang/state?${query}`,\n }),\n {\n credentials: 'include',\n },\n )\n\n if (!response.ok) {\n return\n }\n\n const result = (await response.json()) as TranslationState\n setTranslationState(result)\n }\n\n void loadState()\n }, [collectionSlug, config.routes.api, docID, groupValue])\n\n const selectedLanguageCode = isCreation\n ? languageField.value || preferredCreationLanguage\n : languageField.value && configuredLanguageCodes.has(languageField.value)\n ? languageField.value\n : ''\n const selectedLanguage = languages.find((language) => language.code === selectedLanguageCode)\n const persistedLanguage = !isCreation ? translationState?.language : undefined\n const hasAssignedConfiguredLanguage = Boolean(\n !isCreation &&\n (translationState\n ? persistedLanguage && configuredLanguageCodes.has(persistedLanguage)\n : selectedLanguage),\n )\n\n const collectionAdminURL = (documentID: number | string) =>\n formatAdminURL({\n adminRoute: config.routes.admin,\n path: `/collections/${collectionSlug}/${documentID}`,\n })\n\n const navigateToTranslation = (documentID: number | string) => {\n startRouteTransition(() => {\n router.push(collectionAdminURL(documentID))\n })\n }\n\n const createTranslation = async (targetLanguage: string) => {\n if (!collectionSlug || !docID) {\n toast.error(t('payloadMultilang:saveBeforeCreatingTranslations'))\n return\n }\n\n setBusyLanguage(targetLanguage)\n\n const response = await fetch(\n formatAdminURL({\n apiRoute: config.routes.api,\n path: `/${collectionSlug}/multilang/create`,\n }),\n {\n body: JSON.stringify({\n sourceId: docID,\n targetLanguage,\n }),\n credentials: 'include',\n headers: {\n 'Content-Type': 'application/json',\n },\n method: 'POST',\n },\n )\n\n setBusyLanguage(undefined)\n\n if (!response.ok) {\n const result = (await response.json().catch(() => undefined)) as\n { message?: string } | undefined\n toast.error(result?.message || t('payloadMultilang:translationCouldNotBeCreated'))\n return\n }\n\n const result = (await response.json()) as {\n doc?: { id?: number | string }\n }\n\n if (result.doc?.id) {\n startRouteTransition(() => {\n router.push(collectionAdminURL(result.doc!.id!))\n })\n }\n }\n\n return (\n <section className=\"payload-multilang-metabox\">\n <div className=\"payload-multilang-metabox__header\">\n <h3>{t('payloadMultilang:language')}</h3>\n </div>\n\n <label className=\"payload-multilang-field\">\n <span>{t('payloadMultilang:language')}</span>\n <div className=\"payload-multilang-language-select\">\n <span className=\"payload-multilang-language-select__flag\">\n {selectedLanguage?.flagLabel || '--'}\n </span>\n <select\n disabled={hasAssignedConfiguredLanguage}\n onChange={(event) => languageField.setValue(event.target.value)}\n value={selectedLanguageCode}\n >\n <option value=\"\">{t('payloadMultilang:unassigned')}</option>\n {languages.map((language) => {\n const isCurrent = selectedLanguageCode === language.code\n const isLocalized = localizedLanguageCodes.has(language.code)\n const disabled =\n isCreation || !hasAssignedConfiguredLanguage\n ? isLocalized && !isCurrent\n : true\n\n return (\n <option disabled={disabled} key={language.code} value={language.code}>\n {language.flagLabel ? `${language.flagLabel} ` : ''}\n {language.name}\n </option>\n )\n })}\n </select>\n </div>\n </label>\n\n <div className=\"payload-multilang-translations\" data-testid=\"multilang-sidebar-translations\">\n <h4>{t('payloadMultilang:translations')}</h4>\n {languages.map((language) => {\n const translation = translationState?.translations[language.code]\n const translationID =\n typeof translation?.id === 'number' || typeof translation?.id === 'string'\n ? translation.id\n : undefined\n const isCurrent = isSameDocumentID(translationID, docID)\n const isUnavailableForCreate =\n isCreation && Boolean(translationID) && selectedLanguageCode !== language.code\n\n return (\n <div className=\"payload-multilang-translation-row\" key={language.code}>\n <span className=\"payload-multilang-translation-row__flag\">\n {language.flagLabel || language.code.toUpperCase()}\n </span>\n <span className=\"payload-multilang-translation-row__name\">{language.name}</span>\n {isCurrent ? (\n <span className=\"payload-multilang-translation-row__current\">\n {t('payloadMultilang:current')}\n </span>\n ) : isUnavailableForCreate ? (\n <span className=\"payload-multilang-translation-row__current\">\n {t('payloadMultilang:localized')}\n </span>\n ) : translationID ? (\n <button\n aria-label={t('payloadMultilang:editTranslationFor', {\n language: language.name,\n })}\n className=\"payload-multilang-link-button\"\n disabled={isTransitioning}\n onClick={() => navigateToTranslation(translationID)}\n type=\"button\"\n >\n <PenIcon />\n </button>\n ) : (\n <button\n aria-label={t('payloadMultilang:createTranslationFor', {\n language: language.name,\n })}\n className=\"payload-multilang-icon-button\"\n disabled={!docID || busyLanguage === language.code || isTransitioning}\n onClick={() => void createTranslation(language.code)}\n type=\"button\"\n >\n +\n </button>\n )}\n </div>\n )\n })}\n {!docID ? (\n <div className=\"payload-multilang-muted\">\n {t('payloadMultilang:saveBeforeAddingTranslations')}\n </div>\n ) : null}\n </div>\n </section>\n )\n}\n"],"names":["toast","useConfig","useDocumentInfo","useField","useRouteTransition","useTranslation","useRouter","formatAdminURL","useEffect","useMemo","useState","getCollectionFieldNames","getConfiguredLanguagesFromConfig","getDefaultLanguageFromConfig","PenIcon","svg","aria-hidden","className","fill","height","viewBox","width","xmlns","path","d","stroke","strokeLinejoin","strokeWidth","strokeLinecap","isSameDocumentID","left","right","undefined","String","LanguageMetabox","config","id","collectionSlug","router","isTransitioning","startRouteTransition","t","fieldNames","languageField","language","languages","defaultLanguage","busyLanguage","setBusyLanguage","translationState","setTranslationState","groupField","group","docID","groupValue","value","isCreation","localizedLanguageCodes","Set","Object","keys","translations","configuredLanguageCodes","map","code","availableCreationLanguage","find","has","preferredCreationLanguage","setValue","loadState","query","encodeURIComponent","response","fetch","apiRoute","routes","api","credentials","ok","result","json","selectedLanguageCode","selectedLanguage","persistedLanguage","hasAssignedConfiguredLanguage","Boolean","collectionAdminURL","documentID","adminRoute","admin","navigateToTranslation","push","createTranslation","targetLanguage","error","body","JSON","stringify","sourceId","headers","method","catch","message","doc","section","div","h3","label","span","flagLabel","select","disabled","onChange","event","target","option","isCurrent","isLocalized","name","data-testid","h4","translation","translationID","isUnavailableForCreate","toUpperCase","button","aria-label","onClick","type"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { Button, toast, useConfig, useRouteTransition } from '@payloadcms/ui';
|
|
3
|
+
import { Button, toast, useConfig, useRouteTransition, useTranslation } from '@payloadcms/ui';
|
|
4
4
|
import { useRouter } from 'next/navigation.js';
|
|
5
5
|
import { formatAdminURL } from 'payload/shared';
|
|
6
6
|
import { useState } from 'react';
|
|
@@ -9,6 +9,7 @@ export const TranslationActionsClient = ({ collectionSlug, docID, languages, sta
|
|
|
9
9
|
const { config } = useConfig();
|
|
10
10
|
const router = useRouter();
|
|
11
11
|
const { startRouteTransition } = useRouteTransition();
|
|
12
|
+
const { t } = useTranslation();
|
|
12
13
|
const [targetLanguage, setTargetLanguage] = useState('');
|
|
13
14
|
const [targetID, setTargetID] = useState('');
|
|
14
15
|
const [isBusy, setIsBusy] = useState(false);
|
|
@@ -18,7 +19,7 @@ export const TranslationActionsClient = ({ collectionSlug, docID, languages, sta
|
|
|
18
19
|
});
|
|
19
20
|
const createTranslation = async ()=>{
|
|
20
21
|
if (!targetLanguage) {
|
|
21
|
-
toast.error('
|
|
22
|
+
toast.error(t('payloadMultilang:chooseTargetLanguage'));
|
|
22
23
|
return;
|
|
23
24
|
}
|
|
24
25
|
setIsBusy(true);
|
|
@@ -36,7 +37,7 @@ export const TranslationActionsClient = ({ collectionSlug, docID, languages, sta
|
|
|
36
37
|
setIsBusy(false);
|
|
37
38
|
if (!response.ok) {
|
|
38
39
|
const result = await response.json().catch(()=>undefined);
|
|
39
|
-
toast.error(result?.message || '
|
|
40
|
+
toast.error(result?.message || t('payloadMultilang:translationCouldNotBeCreated'));
|
|
40
41
|
return;
|
|
41
42
|
}
|
|
42
43
|
const result = await response.json();
|
|
@@ -52,7 +53,7 @@ export const TranslationActionsClient = ({ collectionSlug, docID, languages, sta
|
|
|
52
53
|
};
|
|
53
54
|
const connectTranslation = async ()=>{
|
|
54
55
|
if (!targetID || !targetLanguage) {
|
|
55
|
-
toast.error('
|
|
56
|
+
toast.error(t('payloadMultilang:targetIDAndLanguageRequired'));
|
|
56
57
|
return;
|
|
57
58
|
}
|
|
58
59
|
setIsBusy(true);
|
|
@@ -71,10 +72,10 @@ export const TranslationActionsClient = ({ collectionSlug, docID, languages, sta
|
|
|
71
72
|
setIsBusy(false);
|
|
72
73
|
if (!response.ok) {
|
|
73
74
|
const result = await response.json().catch(()=>undefined);
|
|
74
|
-
toast.error(result?.message || '
|
|
75
|
+
toast.error(result?.message || t('payloadMultilang:translationCouldNotBeConnected'));
|
|
75
76
|
return;
|
|
76
77
|
}
|
|
77
|
-
toast.success('
|
|
78
|
+
toast.success(t('payloadMultilang:translationConnected'));
|
|
78
79
|
startRouteTransition(()=>{
|
|
79
80
|
router.refresh();
|
|
80
81
|
});
|
|
@@ -93,10 +94,10 @@ export const TranslationActionsClient = ({ collectionSlug, docID, languages, sta
|
|
|
93
94
|
});
|
|
94
95
|
setIsBusy(false);
|
|
95
96
|
if (!response.ok) {
|
|
96
|
-
toast.error('
|
|
97
|
+
toast.error(t('payloadMultilang:translationCouldNotBeDisconnected'));
|
|
97
98
|
return;
|
|
98
99
|
}
|
|
99
|
-
toast.success('
|
|
100
|
+
toast.success(t('payloadMultilang:translationDisconnected'));
|
|
100
101
|
startRouteTransition(()=>{
|
|
101
102
|
router.refresh();
|
|
102
103
|
});
|
|
@@ -106,7 +107,7 @@ export const TranslationActionsClient = ({ collectionSlug, docID, languages, sta
|
|
|
106
107
|
className: "payload-multilang-panel",
|
|
107
108
|
children: [
|
|
108
109
|
/*#__PURE__*/ _jsx("h2", {
|
|
109
|
-
children:
|
|
110
|
+
children: t('payloadMultilang:translationActions')
|
|
110
111
|
}),
|
|
111
112
|
/*#__PURE__*/ _jsxs("div", {
|
|
112
113
|
className: "payload-multilang-inline-form",
|
|
@@ -117,7 +118,7 @@ export const TranslationActionsClient = ({ collectionSlug, docID, languages, sta
|
|
|
117
118
|
children: [
|
|
118
119
|
/*#__PURE__*/ _jsx("option", {
|
|
119
120
|
value: "",
|
|
120
|
-
children:
|
|
121
|
+
children: t('payloadMultilang:chooseLanguage')
|
|
121
122
|
}),
|
|
122
123
|
availableLanguages.map((language)=>/*#__PURE__*/ _jsxs("option", {
|
|
123
124
|
value: language.code,
|
|
@@ -132,7 +133,7 @@ export const TranslationActionsClient = ({ collectionSlug, docID, languages, sta
|
|
|
132
133
|
disabled: isBusy || !targetLanguage,
|
|
133
134
|
onClick: createTranslation,
|
|
134
135
|
type: "button",
|
|
135
|
-
children:
|
|
136
|
+
children: t('payloadMultilang:createTranslation')
|
|
136
137
|
})
|
|
137
138
|
]
|
|
138
139
|
}),
|
|
@@ -140,15 +141,16 @@ export const TranslationActionsClient = ({ collectionSlug, docID, languages, sta
|
|
|
140
141
|
className: "payload-multilang-inline-form",
|
|
141
142
|
children: [
|
|
142
143
|
/*#__PURE__*/ _jsx("input", {
|
|
144
|
+
"aria-label": t('payloadMultilang:existingDocumentID'),
|
|
143
145
|
onChange: (event)=>setTargetID(event.target.value),
|
|
144
|
-
placeholder:
|
|
146
|
+
placeholder: t('payloadMultilang:existingDocumentID'),
|
|
145
147
|
value: targetID
|
|
146
148
|
}),
|
|
147
149
|
/*#__PURE__*/ _jsx(Button, {
|
|
148
150
|
disabled: isBusy || !targetID || !targetLanguage,
|
|
149
151
|
onClick: connectTranslation,
|
|
150
152
|
type: "button",
|
|
151
|
-
children:
|
|
153
|
+
children: t('payloadMultilang:connectExisting')
|
|
152
154
|
})
|
|
153
155
|
]
|
|
154
156
|
}),
|
|
@@ -157,7 +159,7 @@ export const TranslationActionsClient = ({ collectionSlug, docID, languages, sta
|
|
|
157
159
|
disabled: isBusy,
|
|
158
160
|
onClick: disconnectTranslation,
|
|
159
161
|
type: "button",
|
|
160
|
-
children:
|
|
162
|
+
children: t('payloadMultilang:disconnectDocument')
|
|
161
163
|
})
|
|
162
164
|
]
|
|
163
165
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/TranslationActionsClient.tsx"],"sourcesContent":["'use client'\n\nimport { Button, toast, useConfig, useRouteTransition } from '@payloadcms/ui'\nimport { useRouter } from 'next/navigation.js'\nimport { formatAdminURL } from 'payload/shared'\nimport { useState } from 'react'\n\nimport '../styles/admin.css'\nimport type { MultilangLanguage, TranslationState } from '../types.js'\n\ntype Props = {\n collectionSlug: string\n docID: number | string\n languages: MultilangLanguage[]\n state: TranslationState\n}\n\nexport const TranslationActionsClient = ({\n collectionSlug,\n docID,\n languages,\n state,\n}: Props) => {\n const { config } = useConfig()\n const router = useRouter()\n const { startRouteTransition } = useRouteTransition()\n const [targetLanguage, setTargetLanguage] = useState('')\n const [targetID, setTargetID] = useState('')\n const [isBusy, setIsBusy] = useState(false)\n\n const collectionAPIPath = (path: string) =>\n formatAdminURL({\n apiRoute: config.routes.api,\n path: `/${collectionSlug}${path}`,\n })\n\n const createTranslation = async () => {\n if (!targetLanguage) {\n toast.error('
|
|
1
|
+
{"version":3,"sources":["../../src/components/TranslationActionsClient.tsx"],"sourcesContent":["'use client'\n\nimport { Button, toast, useConfig, useRouteTransition, useTranslation } from '@payloadcms/ui'\nimport { useRouter } from 'next/navigation.js'\nimport { formatAdminURL } from 'payload/shared'\nimport { useState } from 'react'\n\nimport '../styles/admin.css'\nimport type {\n PayloadMultilangTranslationKey,\n PayloadMultilangTranslations,\n} from '../translations.js'\nimport type { MultilangLanguage, TranslationState } from '../types.js'\n\ntype Props = {\n collectionSlug: string\n docID: number | string\n languages: MultilangLanguage[]\n state: TranslationState\n}\n\nexport const TranslationActionsClient = ({\n collectionSlug,\n docID,\n languages,\n state,\n}: Props) => {\n const { config } = useConfig()\n const router = useRouter()\n const { startRouteTransition } = useRouteTransition()\n const { t } = useTranslation<\n PayloadMultilangTranslations,\n PayloadMultilangTranslationKey\n >()\n const [targetLanguage, setTargetLanguage] = useState('')\n const [targetID, setTargetID] = useState('')\n const [isBusy, setIsBusy] = useState(false)\n\n const collectionAPIPath = (path: string) =>\n formatAdminURL({\n apiRoute: config.routes.api,\n path: `/${collectionSlug}${path}`,\n })\n\n const createTranslation = async () => {\n if (!targetLanguage) {\n toast.error(t('payloadMultilang:chooseTargetLanguage'))\n return\n }\n\n setIsBusy(true)\n const response = await fetch(collectionAPIPath('/multilang/create'), {\n body: JSON.stringify({\n sourceId: docID,\n targetLanguage,\n }),\n credentials: 'include',\n headers: {\n 'Content-Type': 'application/json',\n },\n method: 'POST',\n })\n setIsBusy(false)\n\n if (!response.ok) {\n const result = (await response.json().catch(() => undefined)) as\n | { message?: string }\n | undefined\n toast.error(result?.message || t('payloadMultilang:translationCouldNotBeCreated'))\n return\n }\n\n const result = (await response.json()) as { doc?: { id?: number | string } }\n\n const documentID = result.doc?.id\n\n if (documentID) {\n startRouteTransition(() => {\n router.push(\n formatAdminURL({\n adminRoute: config.routes.admin,\n path: `/collections/${collectionSlug}/${documentID}`,\n }),\n )\n })\n }\n }\n\n const connectTranslation = async () => {\n if (!targetID || !targetLanguage) {\n toast.error(t('payloadMultilang:targetIDAndLanguageRequired'))\n return\n }\n\n setIsBusy(true)\n const response = await fetch(collectionAPIPath('/multilang/connect'), {\n body: JSON.stringify({\n sourceId: docID,\n targetId: targetID,\n targetLanguage,\n }),\n credentials: 'include',\n headers: {\n 'Content-Type': 'application/json',\n },\n method: 'POST',\n })\n setIsBusy(false)\n\n if (!response.ok) {\n const result = (await response.json().catch(() => undefined)) as\n | { message?: string }\n | undefined\n toast.error(result?.message || t('payloadMultilang:translationCouldNotBeConnected'))\n return\n }\n\n toast.success(t('payloadMultilang:translationConnected'))\n startRouteTransition(() => {\n router.refresh()\n })\n }\n\n const disconnectTranslation = async () => {\n setIsBusy(true)\n const response = await fetch(collectionAPIPath('/multilang/disconnect'), {\n body: JSON.stringify({ id: docID }),\n credentials: 'include',\n headers: {\n 'Content-Type': 'application/json',\n },\n method: 'POST',\n })\n setIsBusy(false)\n\n if (!response.ok) {\n toast.error(t('payloadMultilang:translationCouldNotBeDisconnected'))\n return\n }\n\n toast.success(t('payloadMultilang:translationDisconnected'))\n startRouteTransition(() => {\n router.refresh()\n })\n }\n\n const availableLanguages = languages.filter(\n (language) => !state.translations[language.code],\n )\n\n return (\n <section className=\"payload-multilang-panel\">\n <h2>{t('payloadMultilang:translationActions')}</h2>\n <div className=\"payload-multilang-inline-form\">\n <select\n onChange={(event) => setTargetLanguage(event.target.value)}\n value={targetLanguage}\n >\n <option value=\"\">{t('payloadMultilang:chooseLanguage')}</option>\n {availableLanguages.map((language) => (\n <option key={language.code} value={language.code}>\n {language.flagLabel ? `${language.flagLabel} ` : ''}\n {language.name}\n </option>\n ))}\n </select>\n <Button disabled={isBusy || !targetLanguage} onClick={createTranslation} type=\"button\">\n {t('payloadMultilang:createTranslation')}\n </Button>\n </div>\n\n <div className=\"payload-multilang-inline-form\">\n <input\n aria-label={t('payloadMultilang:existingDocumentID')}\n onChange={(event) => setTargetID(event.target.value)}\n placeholder={t('payloadMultilang:existingDocumentID')}\n value={targetID}\n />\n <Button disabled={isBusy || !targetID || !targetLanguage} onClick={connectTranslation} type=\"button\">\n {t('payloadMultilang:connectExisting')}\n </Button>\n </div>\n\n <Button buttonStyle=\"secondary\" disabled={isBusy} onClick={disconnectTranslation} type=\"button\">\n {t('payloadMultilang:disconnectDocument')}\n </Button>\n </section>\n )\n}\n"],"names":["Button","toast","useConfig","useRouteTransition","useTranslation","useRouter","formatAdminURL","useState","TranslationActionsClient","collectionSlug","docID","languages","state","config","router","startRouteTransition","t","targetLanguage","setTargetLanguage","targetID","setTargetID","isBusy","setIsBusy","collectionAPIPath","path","apiRoute","routes","api","createTranslation","error","response","fetch","body","JSON","stringify","sourceId","credentials","headers","method","ok","result","json","catch","undefined","message","documentID","doc","id","push","adminRoute","admin","connectTranslation","targetId","success","refresh","disconnectTranslation","availableLanguages","filter","language","translations","code","section","className","h2","div","select","onChange","event","target","value","option","map","flagLabel","name","disabled","onClick","type","input","aria-label","placeholder","buttonStyle"],"mappings":"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"}
|
|
@@ -3,6 +3,7 @@ import { DEFAULT_FIELD_NAMES } from '../constants.js';
|
|
|
3
3
|
import { asDocument, getID, getStringValue } from '../lib/data.js';
|
|
4
4
|
import { getPayloadMultilangCustom } from './config.js';
|
|
5
5
|
import { TranslationColumnCellClient } from './TranslationColumnCellClient.js';
|
|
6
|
+
const translate = (props, key, options)=>props.i18n?.t ? props.i18n.t(key, options) : key;
|
|
6
7
|
const getCollectionConfig = (props)=>props.collectionConfig || props.payload.collections[props.collectionSlug]?.config;
|
|
7
8
|
const getFieldNames = (props)=>({
|
|
8
9
|
...DEFAULT_FIELD_NAMES,
|
|
@@ -53,7 +54,9 @@ export const TranslationColumnCell = async (props)=>{
|
|
|
53
54
|
}
|
|
54
55
|
return /*#__PURE__*/ _jsx("div", {
|
|
55
56
|
className: "payload-multilang-column-stack",
|
|
56
|
-
title: currentLanguage ? undefined : storedLanguage ?
|
|
57
|
+
title: currentLanguage ? undefined : storedLanguage ? translate(props, 'payloadMultilang:unassignedStoredLanguageNotConfigured', {
|
|
58
|
+
language: storedLanguage
|
|
59
|
+
}) : translate(props, 'payloadMultilang:unassigned'),
|
|
57
60
|
children: languages.map((language)=>/*#__PURE__*/ _jsx(TranslationColumnCellClient, {
|
|
58
61
|
collectionSlug: collectionConfig.slug,
|
|
59
62
|
current: currentLanguage === language.code,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/TranslationColumnCell.tsx"],"sourcesContent":["import type {
|
|
1
|
+
{"version":3,"sources":["../../src/components/TranslationColumnCell.tsx"],"sourcesContent":["import type { DefaultServerCellComponentProps } from 'payload'\n\nimport type { PayloadMultilangTranslationKey } from '../translations.js'\nimport type { MultilangFieldNames, MultilangLanguage } from '../types.js'\n\nimport { DEFAULT_FIELD_NAMES } from '../constants.js'\nimport { asDocument, getID, getStringValue } from '../lib/data.js'\nimport { getPayloadMultilangCustom } from './config.js'\nimport { TranslationColumnCellClient } from './TranslationColumnCellClient.js'\n\nconst translate = (\n props: DefaultServerCellComponentProps,\n key: PayloadMultilangTranslationKey,\n options?: Record<string, unknown>,\n): string => props.i18n?.t ? props.i18n.t(key as never, options) : key\n\nconst getCollectionConfig = (props: DefaultServerCellComponentProps) =>\n props.collectionConfig || props.payload.collections[props.collectionSlug]?.config\n\nconst getFieldNames = (\n props: DefaultServerCellComponentProps,\n): MultilangFieldNames => ({\n ...DEFAULT_FIELD_NAMES,\n ...(getPayloadMultilangCustom(getCollectionConfig(props)?.admin?.custom)\n .fieldNames || {}),\n})\n\nconst getLanguages = (\n props: DefaultServerCellComponentProps,\n): MultilangLanguage[] => {\n const languages = getPayloadMultilangCustom(\n getCollectionConfig(props)?.admin?.custom,\n ).languages\n\n return Array.isArray(languages) ? languages : []\n}\n\nexport const TranslationColumnCell = async (\n props: DefaultServerCellComponentProps,\n) => {\n const fieldNames = getFieldNames(props)\n const languages = getLanguages(props)\n const collectionConfig = getCollectionConfig(props)\n const rowData = asDocument(props.rowData)\n const sourceID = getID(rowData.id)\n const configuredLanguageCodes = new Set(languages.map((language) => language.code))\n\n if (!collectionConfig || !languages.length || !sourceID) {\n return (\n <span className=\"payload-multilang-cell payload-multilang-cell--muted\">\n -\n </span>\n )\n }\n\n const storedLanguage = getStringValue(rowData[fieldNames.language])\n const currentLanguage =\n storedLanguage && configuredLanguageCodes.has(storedLanguage)\n ? storedLanguage\n : undefined\n const group = getStringValue(rowData[fieldNames.group])\n let translationsByLanguage: Record<string, number | string> = {}\n\n if (group) {\n const { docs } = await props.payload.find({\n collection: collectionConfig.slug,\n depth: 0,\n limit: 200,\n overrideAccess: true,\n where: {\n [fieldNames.group]: {\n equals: group,\n },\n },\n })\n\n translationsByLanguage = docs.reduce<Record<string, number | string>>(\n (acc, doc) => {\n const data = asDocument(doc)\n const language = getStringValue(data[fieldNames.language])\n const id = getID(data.id)\n\n if (language && id) {\n acc[language] = id\n }\n\n return acc\n },\n {},\n )\n }\n\n return (\n <div\n className=\"payload-multilang-column-stack\"\n title={\n currentLanguage\n ? undefined\n : storedLanguage\n ? translate(\n props,\n 'payloadMultilang:unassignedStoredLanguageNotConfigured',\n { language: storedLanguage },\n )\n : translate(props, 'payloadMultilang:unassigned')\n }\n >\n {languages.map((language) => (\n <TranslationColumnCellClient\n collectionSlug={collectionConfig.slug}\n current={currentLanguage === language.code}\n flagLabel={language.flagLabel}\n key={language.code}\n sourceID={sourceID}\n targetLanguage={language.code}\n targetLanguageName={language.name}\n translationID={translationsByLanguage[language.code]}\n />\n ))}\n </div>\n )\n}\n"],"names":["DEFAULT_FIELD_NAMES","asDocument","getID","getStringValue","getPayloadMultilangCustom","TranslationColumnCellClient","translate","props","key","options","i18n","t","getCollectionConfig","collectionConfig","payload","collections","collectionSlug","config","getFieldNames","admin","custom","fieldNames","getLanguages","languages","Array","isArray","TranslationColumnCell","rowData","sourceID","id","configuredLanguageCodes","Set","map","language","code","length","span","className","storedLanguage","currentLanguage","has","undefined","group","translationsByLanguage","docs","find","collection","slug","depth","limit","overrideAccess","where","equals","reduce","acc","doc","data","div","title","current","flagLabel","targetLanguage","targetLanguageName","name","translationID"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { toast, useConfig, useRouteTransition } from '@payloadcms/ui';
|
|
3
|
+
import { toast, useConfig, useRouteTransition, useTranslation } from '@payloadcms/ui';
|
|
4
4
|
import { useRouter } from 'next/navigation.js';
|
|
5
5
|
import { formatAdminURL } from 'payload/shared';
|
|
6
6
|
import { useState } from 'react';
|
|
@@ -32,6 +32,7 @@ export const TranslationColumnCellClient = ({ collectionSlug, current, flagLabel
|
|
|
32
32
|
const { config } = useConfig();
|
|
33
33
|
const router = useRouter();
|
|
34
34
|
const { isTransitioning, startRouteTransition } = useRouteTransition();
|
|
35
|
+
const { t } = useTranslation();
|
|
35
36
|
const [isBusy, setIsBusy] = useState(false);
|
|
36
37
|
const documentURL = (documentID)=>formatAdminURL({
|
|
37
38
|
adminRoute: config.routes.admin,
|
|
@@ -44,7 +45,7 @@ export const TranslationColumnCellClient = ({ collectionSlug, current, flagLabel
|
|
|
44
45
|
};
|
|
45
46
|
const createTranslation = async ()=>{
|
|
46
47
|
if (!sourceID) {
|
|
47
|
-
toast.error('
|
|
48
|
+
toast.error(t('payloadMultilang:saveBeforeCreatingTranslations'));
|
|
48
49
|
return;
|
|
49
50
|
}
|
|
50
51
|
setIsBusy(true);
|
|
@@ -65,7 +66,7 @@ export const TranslationColumnCellClient = ({ collectionSlug, current, flagLabel
|
|
|
65
66
|
setIsBusy(false);
|
|
66
67
|
if (!response.ok) {
|
|
67
68
|
const result = await response.json().catch(()=>undefined);
|
|
68
|
-
toast.error(result?.message || '
|
|
69
|
+
toast.error(result?.message || t('payloadMultilang:translationCouldNotBeCreated'));
|
|
69
70
|
return;
|
|
70
71
|
}
|
|
71
72
|
const result = await response.json();
|
|
@@ -82,23 +83,31 @@ export const TranslationColumnCellClient = ({ collectionSlug, current, flagLabel
|
|
|
82
83
|
}
|
|
83
84
|
if (translationID) {
|
|
84
85
|
return /*#__PURE__*/ _jsx("a", {
|
|
86
|
+
"aria-label": t('payloadMultilang:editTranslationFor', {
|
|
87
|
+
language: targetLanguageName
|
|
88
|
+
}),
|
|
85
89
|
className: "payload-multilang-cell-action",
|
|
86
90
|
href: documentURL(translationID),
|
|
87
91
|
onClick: (event)=>{
|
|
88
92
|
event.preventDefault();
|
|
89
93
|
navigateToTranslation(translationID);
|
|
90
94
|
},
|
|
91
|
-
|
|
92
|
-
|
|
95
|
+
title: t('payloadMultilang:editTranslationFor', {
|
|
96
|
+
language: targetLanguageName
|
|
97
|
+
}),
|
|
93
98
|
children: /*#__PURE__*/ _jsx(PenIcon, {})
|
|
94
99
|
});
|
|
95
100
|
}
|
|
96
101
|
return /*#__PURE__*/ _jsx("button", {
|
|
97
|
-
"aria-label":
|
|
102
|
+
"aria-label": t('payloadMultilang:createTranslationFor', {
|
|
103
|
+
language: targetLanguageName
|
|
104
|
+
}),
|
|
98
105
|
className: "payload-multilang-icon-button",
|
|
99
106
|
disabled: !sourceID || isBusy || isTransitioning,
|
|
100
107
|
onClick: ()=>void createTranslation(),
|
|
101
|
-
title:
|
|
108
|
+
title: t('payloadMultilang:createTranslationFor', {
|
|
109
|
+
language: targetLanguageName
|
|
110
|
+
}),
|
|
102
111
|
type: "button",
|
|
103
112
|
children: "+"
|
|
104
113
|
});
|