@roxxel/payload-multilang 0.0.5 → 0.0.7

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.
Files changed (39) hide show
  1. package/README.md +16 -3
  2. package/dist/components/LanguageListToolbar.js +4 -3
  3. package/dist/components/LanguageListToolbar.js.map +1 -1
  4. package/dist/components/LanguageMetabox.js +18 -17
  5. package/dist/components/LanguageMetabox.js.map +1 -1
  6. package/dist/components/TranslationActionsClient.js +16 -14
  7. package/dist/components/TranslationActionsClient.js.map +1 -1
  8. package/dist/components/TranslationColumnCell.js +4 -1
  9. package/dist/components/TranslationColumnCell.js.map +1 -1
  10. package/dist/components/TranslationColumnCellClient.js +16 -7
  11. package/dist/components/TranslationColumnCellClient.js.map +1 -1
  12. package/dist/components/TranslationsTab.js +9 -8
  13. package/dist/components/TranslationsTab.js.map +1 -1
  14. package/dist/constants.d.ts +1 -1
  15. package/dist/constants.js +1 -1
  16. package/dist/constants.js.map +1 -1
  17. package/dist/endpoints/translations.js +4 -6
  18. package/dist/endpoints/translations.js.map +1 -1
  19. package/dist/hooks/translatedCollection.d.ts +2 -1
  20. package/dist/hooks/translatedCollection.js +321 -16
  21. package/dist/hooks/translatedCollection.js.map +1 -1
  22. package/dist/hooks/translatedGlobal.js +5 -1
  23. package/dist/hooks/translatedGlobal.js.map +1 -1
  24. package/dist/index.d.ts +1 -0
  25. package/dist/index.js +22 -2
  26. package/dist/index.js.map +1 -1
  27. package/dist/lib/config.js +2 -10
  28. package/dist/lib/config.js.map +1 -1
  29. package/dist/lib/data.d.ts +1 -2
  30. package/dist/lib/data.js +32 -4
  31. package/dist/lib/data.js.map +1 -1
  32. package/dist/translations.d.ts +72 -0
  33. package/dist/translations.js +72 -0
  34. package/dist/translations.js.map +1 -0
  35. package/dist/types.d.ts +0 -19
  36. package/dist/types.js.map +1 -1
  37. package/docs/configuration.md +51 -9
  38. package/docs/usage.md +17 -35
  39. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/TranslationColumnCellClient.tsx"],"sourcesContent":["'use client'\n\nimport { 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'\n\ntype Props = {\n collectionSlug: string\n current?: boolean\n flagLabel?: string\n sourceID?: number | string\n targetLanguage: string\n targetLanguageName: string\n translationID?: number | string\n}\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\n d=\"M8.8 3.9 12.1 7.2\"\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeWidth=\"1.4\"\n />\n </svg>\n)\n\nexport const TranslationColumnCellClient = ({\n collectionSlug,\n current,\n flagLabel,\n sourceID,\n targetLanguage,\n targetLanguageName,\n translationID,\n}: Props) => {\n const { config } = useConfig()\n const router = useRouter()\n const { isTransitioning, startRouteTransition } = useRouteTransition()\n const [isBusy, setIsBusy] = useState(false)\n\n const documentURL = (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(documentURL(documentID))\n })\n }\n\n const createTranslation = async () => {\n if (!sourceID) {\n toast.error('Save the document before creating translations.')\n return\n }\n\n setIsBusy(true)\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: sourceID,\n targetLanguage,\n }),\n credentials: 'include',\n headers: {\n 'Content-Type': 'application/json',\n },\n method: 'POST',\n },\n )\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 || '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 navigateToTranslation(result.doc.id)\n }\n }\n\n if (current) {\n return (\n <span\n className=\"payload-multilang-flag-cell payload-multilang-flag-cell--current\"\n title={targetLanguageName}\n >\n {flagLabel || targetLanguage.toUpperCase()}\n </span>\n )\n }\n\n if (translationID) {\n return (\n <a\n className=\"payload-multilang-cell-action\"\n href={documentURL(translationID)}\n onClick={(event) => {\n event.preventDefault()\n navigateToTranslation(translationID)\n }}\n aria-label={`Edit ${targetLanguageName} translation`}\n title={`Edit ${targetLanguageName} translation`}\n >\n <PenIcon />\n </a>\n )\n }\n\n return (\n <button\n aria-label={`Create ${targetLanguageName} translation`}\n className=\"payload-multilang-icon-button\"\n disabled={!sourceID || isBusy || isTransitioning}\n onClick={() => void createTranslation()}\n title={`Create ${targetLanguageName} translation`}\n type=\"button\"\n >\n +\n </button>\n )\n}\n"],"names":["toast","useConfig","useRouteTransition","useRouter","formatAdminURL","useState","PenIcon","svg","aria-hidden","className","fill","height","viewBox","width","xmlns","path","d","stroke","strokeLinejoin","strokeWidth","strokeLinecap","TranslationColumnCellClient","collectionSlug","current","flagLabel","sourceID","targetLanguage","targetLanguageName","translationID","config","router","isTransitioning","startRouteTransition","isBusy","setIsBusy","documentURL","documentID","adminRoute","routes","admin","navigateToTranslation","push","createTranslation","error","response","fetch","apiRoute","api","body","JSON","stringify","sourceId","credentials","headers","method","ok","result","json","catch","undefined","message","doc","id","span","title","toUpperCase","a","href","onClick","event","preventDefault","aria-label","button","disabled","type"],"mappings":"AAAA;;AAEA,SAASA,KAAK,EAAEC,SAAS,EAAEC,kBAAkB,QAAQ,iBAAgB;AACrE,SAASC,SAAS,QAAQ,qBAAoB;AAC9C,SAASC,cAAc,QAAQ,iBAAgB;AAC/C,SAASC,QAAQ,QAAQ,QAAO;AAEhC,OAAO,sBAAqB;AAY5B,MAAMC,UAAU,kBACd,MAACC;QACCC,eAAY;QACZC,WAAU;QACVC,MAAK;QACLC,QAAO;QACPC,SAAQ;QACRC,OAAM;QACNC,OAAM;;0BAEN,KAACC;gBACCC,GAAE;gBACFC,QAAO;gBACPC,gBAAe;gBACfC,aAAY;;0BAEd,KAACJ;gBACCC,GAAE;gBACFC,QAAO;gBACPG,eAAc;gBACdD,aAAY;;;;AAKlB,OAAO,MAAME,8BAA8B,CAAC,EAC1CC,cAAc,EACdC,OAAO,EACPC,SAAS,EACTC,QAAQ,EACRC,cAAc,EACdC,kBAAkB,EAClBC,aAAa,EACP;IACN,MAAM,EAAEC,MAAM,EAAE,GAAG5B;IACnB,MAAM6B,SAAS3B;IACf,MAAM,EAAE4B,eAAe,EAAEC,oBAAoB,EAAE,GAAG9B;IAClD,MAAM,CAAC+B,QAAQC,UAAU,GAAG7B,SAAS;IAErC,MAAM8B,cAAc,CAACC,aACnBhC,eAAe;YACbiC,YAAYR,OAAOS,MAAM,CAACC,KAAK;YAC/BxB,MAAM,CAAC,aAAa,EAAEO,eAAe,CAAC,EAAEc,YAAY;QACtD;IAEF,MAAMI,wBAAwB,CAACJ;QAC7BJ,qBAAqB;YACnBF,OAAOW,IAAI,CAACN,YAAYC;QAC1B;IACF;IAEA,MAAMM,oBAAoB;QACxB,IAAI,CAACjB,UAAU;YACbzB,MAAM2C,KAAK,CAAC;YACZ;QACF;QAEAT,UAAU;QAEV,MAAMU,WAAW,MAAMC,MACrBzC,eAAe;YACb0C,UAAUjB,OAAOS,MAAM,CAACS,GAAG;YAC3BhC,MAAM,CAAC,CAAC,EAAEO,eAAe,iBAAiB,CAAC;QAC7C,IACA;YACE0B,MAAMC,KAAKC,SAAS,CAAC;gBACnBC,UAAU1B;gBACVC;YACF;YACA0B,aAAa;YACbC,SAAS;gBACP,gBAAgB;YAClB;YACAC,QAAQ;QACV;QAGFpB,UAAU;QAEV,IAAI,CAACU,SAASW,EAAE,EAAE;YAChB,MAAMC,SAAU,MAAMZ,SAASa,IAAI,GAAGC,KAAK,CAAC,IAAMC;YAGlD3D,MAAM2C,KAAK,CAACa,QAAQI,WAAW;YAC/B;QACF;QAEA,MAAMJ,SAAU,MAAMZ,SAASa,IAAI;QAInC,IAAID,OAAOK,GAAG,EAAEC,IAAI;YAClBtB,sBAAsBgB,OAAOK,GAAG,CAACC,EAAE;QACrC;IACF;IAEA,IAAIvC,SAAS;QACX,qBACE,KAACwC;YACCtD,WAAU;YACVuD,OAAOrC;sBAENH,aAAaE,eAAeuC,WAAW;;IAG9C;IAEA,IAAIrC,eAAe;QACjB,qBACE,KAACsC;YACCzD,WAAU;YACV0D,MAAMhC,YAAYP;YAClBwC,SAAS,CAACC;gBACRA,MAAMC,cAAc;gBACpB9B,sBAAsBZ;YACxB;YACA2C,cAAY,CAAC,KAAK,EAAE5C,mBAAmB,YAAY,CAAC;YACpDqC,OAAO,CAAC,KAAK,EAAErC,mBAAmB,YAAY,CAAC;sBAE/C,cAAA,KAACrB;;IAGP;IAEA,qBACE,KAACkE;QACCD,cAAY,CAAC,OAAO,EAAE5C,mBAAmB,YAAY,CAAC;QACtDlB,WAAU;QACVgE,UAAU,CAAChD,YAAYQ,UAAUF;QACjCqC,SAAS,IAAM,KAAK1B;QACpBsB,OAAO,CAAC,OAAO,EAAErC,mBAAmB,YAAY,CAAC;QACjD+C,MAAK;kBACN;;AAIL,EAAC"}
1
+ {"version":3,"sources":["../../src/components/TranslationColumnCellClient.tsx"],"sourcesContent":["'use client'\n\nimport { 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'\n\ntype Props = {\n collectionSlug: string\n current?: boolean\n flagLabel?: string\n sourceID?: number | string\n targetLanguage: string\n targetLanguageName: string\n translationID?: number | string\n}\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\n d=\"M8.8 3.9 12.1 7.2\"\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeWidth=\"1.4\"\n />\n </svg>\n)\n\nexport const TranslationColumnCellClient = ({\n collectionSlug,\n current,\n flagLabel,\n sourceID,\n targetLanguage,\n targetLanguageName,\n translationID,\n}: Props) => {\n const { config } = useConfig()\n const router = useRouter()\n const { isTransitioning, startRouteTransition } = useRouteTransition()\n const { t } = useTranslation<\n PayloadMultilangTranslations,\n PayloadMultilangTranslationKey\n >()\n const [isBusy, setIsBusy] = useState(false)\n\n const documentURL = (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(documentURL(documentID))\n })\n }\n\n const createTranslation = async () => {\n if (!sourceID) {\n toast.error(t('payloadMultilang:saveBeforeCreatingTranslations'))\n return\n }\n\n setIsBusy(true)\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: sourceID,\n targetLanguage,\n }),\n credentials: 'include',\n headers: {\n 'Content-Type': 'application/json',\n },\n method: 'POST',\n },\n )\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 {\n doc?: { id?: number | string }\n }\n\n if (result.doc?.id) {\n navigateToTranslation(result.doc.id)\n }\n }\n\n if (current) {\n return (\n <span\n className=\"payload-multilang-flag-cell payload-multilang-flag-cell--current\"\n title={targetLanguageName}\n >\n {flagLabel || targetLanguage.toUpperCase()}\n </span>\n )\n }\n\n if (translationID) {\n return (\n <a\n aria-label={t('payloadMultilang:editTranslationFor', {\n language: targetLanguageName,\n })}\n className=\"payload-multilang-cell-action\"\n href={documentURL(translationID)}\n onClick={(event) => {\n event.preventDefault()\n navigateToTranslation(translationID)\n }}\n title={t('payloadMultilang:editTranslationFor', {\n language: targetLanguageName,\n })}\n >\n <PenIcon />\n </a>\n )\n }\n\n return (\n <button\n aria-label={t('payloadMultilang:createTranslationFor', {\n language: targetLanguageName,\n })}\n className=\"payload-multilang-icon-button\"\n disabled={!sourceID || isBusy || isTransitioning}\n onClick={() => void createTranslation()}\n title={t('payloadMultilang:createTranslationFor', {\n language: targetLanguageName,\n })}\n type=\"button\"\n >\n +\n </button>\n )\n}\n"],"names":["toast","useConfig","useRouteTransition","useTranslation","useRouter","formatAdminURL","useState","PenIcon","svg","aria-hidden","className","fill","height","viewBox","width","xmlns","path","d","stroke","strokeLinejoin","strokeWidth","strokeLinecap","TranslationColumnCellClient","collectionSlug","current","flagLabel","sourceID","targetLanguage","targetLanguageName","translationID","config","router","isTransitioning","startRouteTransition","t","isBusy","setIsBusy","documentURL","documentID","adminRoute","routes","admin","navigateToTranslation","push","createTranslation","error","response","fetch","apiRoute","api","body","JSON","stringify","sourceId","credentials","headers","method","ok","result","json","catch","undefined","message","doc","id","span","title","toUpperCase","a","aria-label","language","href","onClick","event","preventDefault","button","disabled","type"],"mappings":"AAAA;;AAEA,SAASA,KAAK,EAAEC,SAAS,EAAEC,kBAAkB,EAAEC,cAAc,QAAQ,iBAAgB;AACrF,SAASC,SAAS,QAAQ,qBAAoB;AAC9C,SAASC,cAAc,QAAQ,iBAAgB;AAC/C,SAASC,QAAQ,QAAQ,QAAO;AAEhC,OAAO,sBAAqB;AAgB5B,MAAMC,UAAU,kBACd,MAACC;QACCC,eAAY;QACZC,WAAU;QACVC,MAAK;QACLC,QAAO;QACPC,SAAQ;QACRC,OAAM;QACNC,OAAM;;0BAEN,KAACC;gBACCC,GAAE;gBACFC,QAAO;gBACPC,gBAAe;gBACfC,aAAY;;0BAEd,KAACJ;gBACCC,GAAE;gBACFC,QAAO;gBACPG,eAAc;gBACdD,aAAY;;;;AAKlB,OAAO,MAAME,8BAA8B,CAAC,EAC1CC,cAAc,EACdC,OAAO,EACPC,SAAS,EACTC,QAAQ,EACRC,cAAc,EACdC,kBAAkB,EAClBC,aAAa,EACP;IACN,MAAM,EAAEC,MAAM,EAAE,GAAG7B;IACnB,MAAM8B,SAAS3B;IACf,MAAM,EAAE4B,eAAe,EAAEC,oBAAoB,EAAE,GAAG/B;IAClD,MAAM,EAAEgC,CAAC,EAAE,GAAG/B;IAId,MAAM,CAACgC,QAAQC,UAAU,GAAG9B,SAAS;IAErC,MAAM+B,cAAc,CAACC,aACnBjC,eAAe;YACbkC,YAAYT,OAAOU,MAAM,CAACC,KAAK;YAC/BzB,MAAM,CAAC,aAAa,EAAEO,eAAe,CAAC,EAAEe,YAAY;QACtD;IAEF,MAAMI,wBAAwB,CAACJ;QAC7BL,qBAAqB;YACnBF,OAAOY,IAAI,CAACN,YAAYC;QAC1B;IACF;IAEA,MAAMM,oBAAoB;QACxB,IAAI,CAAClB,UAAU;YACb1B,MAAM6C,KAAK,CAACX,EAAE;YACd;QACF;QAEAE,UAAU;QAEV,MAAMU,WAAW,MAAMC,MACrB1C,eAAe;YACb2C,UAAUlB,OAAOU,MAAM,CAACS,GAAG;YAC3BjC,MAAM,CAAC,CAAC,EAAEO,eAAe,iBAAiB,CAAC;QAC7C,IACA;YACE2B,MAAMC,KAAKC,SAAS,CAAC;gBACnBC,UAAU3B;gBACVC;YACF;YACA2B,aAAa;YACbC,SAAS;gBACP,gBAAgB;YAClB;YACAC,QAAQ;QACV;QAGFpB,UAAU;QAEV,IAAI,CAACU,SAASW,EAAE,EAAE;YAChB,MAAMC,SAAU,MAAMZ,SAASa,IAAI,GAAGC,KAAK,CAAC,IAAMC;YAGlD7D,MAAM6C,KAAK,CAACa,QAAQI,WAAW5B,EAAE;YACjC;QACF;QAEA,MAAMwB,SAAU,MAAMZ,SAASa,IAAI;QAInC,IAAID,OAAOK,GAAG,EAAEC,IAAI;YAClBtB,sBAAsBgB,OAAOK,GAAG,CAACC,EAAE;QACrC;IACF;IAEA,IAAIxC,SAAS;QACX,qBACE,KAACyC;YACCvD,WAAU;YACVwD,OAAOtC;sBAENH,aAAaE,eAAewC,WAAW;;IAG9C;IAEA,IAAItC,eAAe;QACjB,qBACE,KAACuC;YACCC,cAAYnC,EAAE,uCAAuC;gBACnDoC,UAAU1C;YACZ;YACAlB,WAAU;YACV6D,MAAMlC,YAAYR;YAClB2C,SAAS,CAACC;gBACRA,MAAMC,cAAc;gBACpBhC,sBAAsBb;YACxB;YACAqC,OAAOhC,EAAE,uCAAuC;gBAC9CoC,UAAU1C;YACZ;sBAEA,cAAA,KAACrB;;IAGP;IAEA,qBACE,KAACoE;QACCN,cAAYnC,EAAE,yCAAyC;YACrDoC,UAAU1C;QACZ;QACAlB,WAAU;QACVkE,UAAU,CAAClD,YAAYS,UAAUH;QACjCwC,SAAS,IAAM,KAAK5B;QACpBsB,OAAOhC,EAAE,yCAAyC;YAChDoC,UAAU1C;QACZ;QACAiD,MAAK;kBACN;;AAIL,EAAC"}
@@ -14,6 +14,7 @@ const getLanguages = (props)=>{
14
14
  const languages = getPayloadMultilangCustom(props.initPageResult.collectionConfig?.admin?.custom).languages;
15
15
  return Array.isArray(languages) ? languages : [];
16
16
  };
17
+ const translate = (props, key, options)=>props.i18n?.t ? props.i18n.t(key, options) : key;
17
18
  export const TranslationsTab = async (props)=>{
18
19
  const collectionSlug = props.initPageResult.collectionConfig?.slug;
19
20
  const translationsSegmentIndex = props.routeSegments.lastIndexOf('translations');
@@ -24,10 +25,10 @@ export const TranslationsTab = async (props)=>{
24
25
  className: "payload-multilang-page",
25
26
  children: [
26
27
  /*#__PURE__*/ _jsx("h1", {
27
- children: "Translations"
28
+ children: translate(props, 'payloadMultilang:translations')
28
29
  }),
29
30
  /*#__PURE__*/ _jsx("p", {
30
- children: "Save the document before managing translations."
31
+ children: translate(props, 'payloadMultilang:saveBeforeManagingTranslations')
31
32
  })
32
33
  ]
33
34
  });
@@ -49,10 +50,10 @@ export const TranslationsTab = async (props)=>{
49
50
  children: /*#__PURE__*/ _jsxs("div", {
50
51
  children: [
51
52
  /*#__PURE__*/ _jsx("h1", {
52
- children: "Translations"
53
+ children: translate(props, 'payloadMultilang:translations')
53
54
  }),
54
55
  /*#__PURE__*/ _jsx("p", {
55
- children: "Create or connect separate localized documents."
56
+ children: translate(props, 'payloadMultilang:createOrConnectDocuments')
56
57
  })
57
58
  ]
58
59
  })
@@ -64,7 +65,7 @@ export const TranslationsTab = async (props)=>{
64
65
  className: "payload-multilang-panel payload-multilang-panel--wide",
65
66
  children: [
66
67
  /*#__PURE__*/ _jsx("h2", {
67
- children: "Linked documents"
68
+ children: translate(props, 'payloadMultilang:linkedDocuments')
68
69
  }),
69
70
  /*#__PURE__*/ _jsxs("table", {
70
71
  className: "payload-multilang-table",
@@ -73,10 +74,10 @@ export const TranslationsTab = async (props)=>{
73
74
  children: /*#__PURE__*/ _jsxs("tr", {
74
75
  children: [
75
76
  /*#__PURE__*/ _jsx("th", {
76
- children: "Language"
77
+ children: translate(props, 'payloadMultilang:language')
77
78
  }),
78
79
  /*#__PURE__*/ _jsx("th", {
79
- children: "Document ID"
80
+ children: translate(props, 'payloadMultilang:documentID')
80
81
  })
81
82
  ]
82
83
  })
@@ -93,7 +94,7 @@ export const TranslationsTab = async (props)=>{
93
94
  ]
94
95
  }),
95
96
  /*#__PURE__*/ _jsx("td", {
96
- children: translation?.id ? String(translation.id) : 'Missing'
97
+ children: translation?.id ? String(translation.id) : translate(props, 'payloadMultilang:missing')
97
98
  })
98
99
  ]
99
100
  }, language.code);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/TranslationsTab.tsx"],"sourcesContent":["import type { DocumentViewServerProps } from 'payload'\n\nimport type { MultilangFieldNames, MultilangLanguage } from '../types.js'\n\nimport { DEFAULT_FIELD_NAMES } from '../constants.js'\nimport {\n asDocument,\n getDocumentTranslationsWithPayload,\n getID,\n} from '../lib/data.js'\nimport { getPayloadMultilangCustom } from './config.js'\nimport { TranslationActionsClient } from './TranslationActionsClient.js'\n\nconst getFieldNames = (\n props: DocumentViewServerProps,\n): MultilangFieldNames => {\n const custom = props.initPageResult.collectionConfig?.admin?.custom as\n | { payloadMultilang?: { fieldNames?: Partial<MultilangFieldNames> } }\n | undefined\n\n return {\n ...DEFAULT_FIELD_NAMES,\n ...(custom?.payloadMultilang?.fieldNames || {}),\n }\n}\n\nconst getLanguages = (props: DocumentViewServerProps): MultilangLanguage[] => {\n const languages = getPayloadMultilangCustom(\n props.initPageResult.collectionConfig?.admin?.custom,\n ).languages\n\n return Array.isArray(languages) ? languages : []\n}\n\nexport const TranslationsTab = async (props: DocumentViewServerProps) => {\n const collectionSlug = props.initPageResult.collectionConfig?.slug\n const translationsSegmentIndex = props.routeSegments.lastIndexOf('translations')\n const routeDocID =\n translationsSegmentIndex > 0 ? props.routeSegments[translationsSegmentIndex - 1] : undefined\n const docID = getID(asDocument(props.doc).id || routeDocID || props.id)\n\n if (!collectionSlug || !docID) {\n return (\n <section className=\"payload-multilang-page\">\n <h1>Translations</h1>\n <p>Save the document before managing translations.</p>\n </section>\n )\n }\n\n const fieldNames = getFieldNames(props)\n const languages = getLanguages(props)\n const state = await getDocumentTranslationsWithPayload({\n id: docID,\n collection: collectionSlug,\n fieldNames,\n payload: props.payload,\n })\n\n return (\n <div className=\"payload-multilang-page\" data-testid=\"multilang-translations-tab\">\n <header className=\"payload-multilang-page__header\">\n <div>\n <h1>Translations</h1>\n <p>Create or connect separate localized documents.</p>\n </div>\n </header>\n\n <div className=\"payload-multilang-layout\">\n <section className=\"payload-multilang-panel payload-multilang-panel--wide\">\n <h2>Linked documents</h2>\n <table className=\"payload-multilang-table\">\n <thead>\n <tr>\n <th>Language</th>\n <th>Document ID</th>\n </tr>\n </thead>\n <tbody>\n {languages.map((language) => {\n const translation = state.translations[language.code]\n return (\n <tr key={language.code}>\n <td>\n {language.flagLabel ? `${language.flagLabel} ` : ''}\n {language.name}\n </td>\n <td>{translation?.id ? String(translation.id) : 'Missing'}</td>\n </tr>\n )\n })}\n </tbody>\n </table>\n </section>\n\n <TranslationActionsClient\n collectionSlug={collectionSlug}\n docID={docID}\n languages={languages}\n state={state}\n />\n </div>\n </div>\n )\n}\n"],"names":["DEFAULT_FIELD_NAMES","asDocument","getDocumentTranslationsWithPayload","getID","getPayloadMultilangCustom","TranslationActionsClient","getFieldNames","props","custom","initPageResult","collectionConfig","admin","payloadMultilang","fieldNames","getLanguages","languages","Array","isArray","TranslationsTab","collectionSlug","slug","translationsSegmentIndex","routeSegments","lastIndexOf","routeDocID","undefined","docID","doc","id","section","className","h1","p","state","collection","payload","div","data-testid","header","h2","table","thead","tr","th","tbody","map","language","translation","translations","code","td","flagLabel","name","String"],"mappings":";AAIA,SAASA,mBAAmB,QAAQ,kBAAiB;AACrD,SACEC,UAAU,EACVC,kCAAkC,EAClCC,KAAK,QACA,iBAAgB;AACvB,SAASC,yBAAyB,QAAQ,cAAa;AACvD,SAASC,wBAAwB,QAAQ,gCAA+B;AAExE,MAAMC,gBAAgB,CACpBC;IAEA,MAAMC,SAASD,MAAME,cAAc,CAACC,gBAAgB,EAAEC,OAAOH;IAI7D,OAAO;QACL,GAAGR,mBAAmB;QACtB,GAAIQ,QAAQI,kBAAkBC,cAAc,CAAC,CAAC;IAChD;AACF;AAEA,MAAMC,eAAe,CAACP;IACpB,MAAMQ,YAAYX,0BAChBG,MAAME,cAAc,CAACC,gBAAgB,EAAEC,OAAOH,QAC9CO,SAAS;IAEX,OAAOC,MAAMC,OAAO,CAACF,aAAaA,YAAY,EAAE;AAClD;AAEA,OAAO,MAAMG,kBAAkB,OAAOX;IACpC,MAAMY,iBAAiBZ,MAAME,cAAc,CAACC,gBAAgB,EAAEU;IAC9D,MAAMC,2BAA2Bd,MAAMe,aAAa,CAACC,WAAW,CAAC;IACjE,MAAMC,aACJH,2BAA2B,IAAId,MAAMe,aAAa,CAACD,2BAA2B,EAAE,GAAGI;IACrF,MAAMC,QAAQvB,MAAMF,WAAWM,MAAMoB,GAAG,EAAEC,EAAE,IAAIJ,cAAcjB,MAAMqB,EAAE;IAEtE,IAAI,CAACT,kBAAkB,CAACO,OAAO;QAC7B,qBACE,MAACG;YAAQC,WAAU;;8BACjB,KAACC;8BAAG;;8BACJ,KAACC;8BAAE;;;;IAGT;IAEA,MAAMnB,aAAaP,cAAcC;IACjC,MAAMQ,YAAYD,aAAaP;IAC/B,MAAM0B,QAAQ,MAAM/B,mCAAmC;QACrD0B,IAAIF;QACJQ,YAAYf;QACZN;QACAsB,SAAS5B,MAAM4B,OAAO;IACxB;IAEA,qBACE,MAACC;QAAIN,WAAU;QAAyBO,eAAY;;0BAClD,KAACC;gBAAOR,WAAU;0BAChB,cAAA,MAACM;;sCACC,KAACL;sCAAG;;sCACJ,KAACC;sCAAE;;;;;0BAIP,MAACI;gBAAIN,WAAU;;kCACb,MAACD;wBAAQC,WAAU;;0CACjB,KAACS;0CAAG;;0CACJ,MAACC;gCAAMV,WAAU;;kDACf,KAACW;kDACC,cAAA,MAACC;;8DACC,KAACC;8DAAG;;8DACJ,KAACA;8DAAG;;;;;kDAGR,KAACC;kDACE7B,UAAU8B,GAAG,CAAC,CAACC;4CACd,MAAMC,cAAcd,MAAMe,YAAY,CAACF,SAASG,IAAI,CAAC;4CACrD,qBACE,MAACP;;kEACC,MAACQ;;4DACEJ,SAASK,SAAS,GAAG,GAAGL,SAASK,SAAS,CAAC,CAAC,CAAC,GAAG;4DAChDL,SAASM,IAAI;;;kEAEhB,KAACF;kEAAIH,aAAanB,KAAKyB,OAAON,YAAYnB,EAAE,IAAI;;;+CALzCkB,SAASG,IAAI;wCAQ1B;;;;;;kCAKN,KAAC5C;wBACCc,gBAAgBA;wBAChBO,OAAOA;wBACPX,WAAWA;wBACXkB,OAAOA;;;;;;AAKjB,EAAC"}
1
+ {"version":3,"sources":["../../src/components/TranslationsTab.tsx"],"sourcesContent":["import type { DocumentViewServerProps } 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 {\n asDocument,\n getDocumentTranslationsWithPayload,\n getID,\n} from '../lib/data.js'\nimport { getPayloadMultilangCustom } from './config.js'\nimport { TranslationActionsClient } from './TranslationActionsClient.js'\n\nconst getFieldNames = (\n props: DocumentViewServerProps,\n): MultilangFieldNames => {\n const custom = props.initPageResult.collectionConfig?.admin?.custom as\n | { payloadMultilang?: { fieldNames?: Partial<MultilangFieldNames> } }\n | undefined\n\n return {\n ...DEFAULT_FIELD_NAMES,\n ...(custom?.payloadMultilang?.fieldNames || {}),\n }\n}\n\nconst getLanguages = (props: DocumentViewServerProps): MultilangLanguage[] => {\n const languages = getPayloadMultilangCustom(\n props.initPageResult.collectionConfig?.admin?.custom,\n ).languages\n\n return Array.isArray(languages) ? languages : []\n}\n\nconst translate = (\n props: DocumentViewServerProps,\n key: PayloadMultilangTranslationKey,\n options?: Record<string, unknown>,\n): string => props.i18n?.t ? props.i18n.t(key as never, options) : key\n\nexport const TranslationsTab = async (props: DocumentViewServerProps) => {\n const collectionSlug = props.initPageResult.collectionConfig?.slug\n const translationsSegmentIndex = props.routeSegments.lastIndexOf('translations')\n const routeDocID =\n translationsSegmentIndex > 0 ? props.routeSegments[translationsSegmentIndex - 1] : undefined\n const docID = getID(asDocument(props.doc).id || routeDocID || props.id)\n\n if (!collectionSlug || !docID) {\n return (\n <section className=\"payload-multilang-page\">\n <h1>{translate(props, 'payloadMultilang:translations')}</h1>\n <p>{translate(props, 'payloadMultilang:saveBeforeManagingTranslations')}</p>\n </section>\n )\n }\n\n const fieldNames = getFieldNames(props)\n const languages = getLanguages(props)\n const state = await getDocumentTranslationsWithPayload({\n id: docID,\n collection: collectionSlug,\n fieldNames,\n payload: props.payload,\n })\n\n return (\n <div className=\"payload-multilang-page\" data-testid=\"multilang-translations-tab\">\n <header className=\"payload-multilang-page__header\">\n <div>\n <h1>{translate(props, 'payloadMultilang:translations')}</h1>\n <p>{translate(props, 'payloadMultilang:createOrConnectDocuments')}</p>\n </div>\n </header>\n\n <div className=\"payload-multilang-layout\">\n <section className=\"payload-multilang-panel payload-multilang-panel--wide\">\n <h2>{translate(props, 'payloadMultilang:linkedDocuments')}</h2>\n <table className=\"payload-multilang-table\">\n <thead>\n <tr>\n <th>{translate(props, 'payloadMultilang:language')}</th>\n <th>{translate(props, 'payloadMultilang:documentID')}</th>\n </tr>\n </thead>\n <tbody>\n {languages.map((language) => {\n const translation = state.translations[language.code]\n return (\n <tr key={language.code}>\n <td>\n {language.flagLabel ? `${language.flagLabel} ` : ''}\n {language.name}\n </td>\n <td>\n {translation?.id\n ? String(translation.id)\n : translate(props, 'payloadMultilang:missing')}\n </td>\n </tr>\n )\n })}\n </tbody>\n </table>\n </section>\n\n <TranslationActionsClient\n collectionSlug={collectionSlug}\n docID={docID}\n languages={languages}\n state={state}\n />\n </div>\n </div>\n )\n}\n"],"names":["DEFAULT_FIELD_NAMES","asDocument","getDocumentTranslationsWithPayload","getID","getPayloadMultilangCustom","TranslationActionsClient","getFieldNames","props","custom","initPageResult","collectionConfig","admin","payloadMultilang","fieldNames","getLanguages","languages","Array","isArray","translate","key","options","i18n","t","TranslationsTab","collectionSlug","slug","translationsSegmentIndex","routeSegments","lastIndexOf","routeDocID","undefined","docID","doc","id","section","className","h1","p","state","collection","payload","div","data-testid","header","h2","table","thead","tr","th","tbody","map","language","translation","translations","code","td","flagLabel","name","String"],"mappings":";AAKA,SAASA,mBAAmB,QAAQ,kBAAiB;AACrD,SACEC,UAAU,EACVC,kCAAkC,EAClCC,KAAK,QACA,iBAAgB;AACvB,SAASC,yBAAyB,QAAQ,cAAa;AACvD,SAASC,wBAAwB,QAAQ,gCAA+B;AAExE,MAAMC,gBAAgB,CACpBC;IAEA,MAAMC,SAASD,MAAME,cAAc,CAACC,gBAAgB,EAAEC,OAAOH;IAI7D,OAAO;QACL,GAAGR,mBAAmB;QACtB,GAAIQ,QAAQI,kBAAkBC,cAAc,CAAC,CAAC;IAChD;AACF;AAEA,MAAMC,eAAe,CAACP;IACpB,MAAMQ,YAAYX,0BAChBG,MAAME,cAAc,CAACC,gBAAgB,EAAEC,OAAOH,QAC9CO,SAAS;IAEX,OAAOC,MAAMC,OAAO,CAACF,aAAaA,YAAY,EAAE;AAClD;AAEA,MAAMG,YAAY,CAChBX,OACAY,KACAC,UACWb,MAAMc,IAAI,EAAEC,IAAIf,MAAMc,IAAI,CAACC,CAAC,CAACH,KAAcC,WAAWD;AAEnE,OAAO,MAAMI,kBAAkB,OAAOhB;IACpC,MAAMiB,iBAAiBjB,MAAME,cAAc,CAACC,gBAAgB,EAAEe;IAC9D,MAAMC,2BAA2BnB,MAAMoB,aAAa,CAACC,WAAW,CAAC;IACjE,MAAMC,aACJH,2BAA2B,IAAInB,MAAMoB,aAAa,CAACD,2BAA2B,EAAE,GAAGI;IACrF,MAAMC,QAAQ5B,MAAMF,WAAWM,MAAMyB,GAAG,EAAEC,EAAE,IAAIJ,cAActB,MAAM0B,EAAE;IAEtE,IAAI,CAACT,kBAAkB,CAACO,OAAO;QAC7B,qBACE,MAACG;YAAQC,WAAU;;8BACjB,KAACC;8BAAIlB,UAAUX,OAAO;;8BACtB,KAAC8B;8BAAGnB,UAAUX,OAAO;;;;IAG3B;IAEA,MAAMM,aAAaP,cAAcC;IACjC,MAAMQ,YAAYD,aAAaP;IAC/B,MAAM+B,QAAQ,MAAMpC,mCAAmC;QACrD+B,IAAIF;QACJQ,YAAYf;QACZX;QACA2B,SAASjC,MAAMiC,OAAO;IACxB;IAEA,qBACE,MAACC;QAAIN,WAAU;QAAyBO,eAAY;;0BAClD,KAACC;gBAAOR,WAAU;0BAChB,cAAA,MAACM;;sCACC,KAACL;sCAAIlB,UAAUX,OAAO;;sCACtB,KAAC8B;sCAAGnB,UAAUX,OAAO;;;;;0BAIzB,MAACkC;gBAAIN,WAAU;;kCACb,MAACD;wBAAQC,WAAU;;0CACjB,KAACS;0CAAI1B,UAAUX,OAAO;;0CACtB,MAACsC;gCAAMV,WAAU;;kDACf,KAACW;kDACC,cAAA,MAACC;;8DACC,KAACC;8DAAI9B,UAAUX,OAAO;;8DACtB,KAACyC;8DAAI9B,UAAUX,OAAO;;;;;kDAG1B,KAAC0C;kDACElC,UAAUmC,GAAG,CAAC,CAACC;4CACd,MAAMC,cAAcd,MAAMe,YAAY,CAACF,SAASG,IAAI,CAAC;4CACrD,qBACE,MAACP;;kEACC,MAACQ;;4DACEJ,SAASK,SAAS,GAAG,GAAGL,SAASK,SAAS,CAAC,CAAC,CAAC,GAAG;4DAChDL,SAASM,IAAI;;;kEAEhB,KAACF;kEACEH,aAAanB,KACVyB,OAAON,YAAYnB,EAAE,IACrBf,UAAUX,OAAO;;;+CARhB4C,SAASG,IAAI;wCAY1B;;;;;;kCAKN,KAACjD;wBACCmB,gBAAgBA;wBAChBO,OAAOA;wBACPhB,WAAWA;wBACXuB,OAAOA;;;;;;AAKjB,EAAC"}
@@ -4,5 +4,5 @@ export declare const MULTILANG_GROUP_FIELD: string;
4
4
  export declare const MULTILANG_LANGUAGE_FIELD: string;
5
5
  export declare const MULTILANG_META_FIELD: string;
6
6
  export declare const DEFAULT_GLOBAL_TABS_LABEL = "Localized content";
7
- export declare const DEFAULT_DUPLICATE_EXCLUDE_FIELDS: string[];
7
+ export declare const SYSTEM_DUPLICATION_EXCLUDED_FIELDS: string[];
8
8
  export declare const MULTILANG_SKIP_HOOK = "payloadMultilangSkip";
package/dist/constants.js CHANGED
@@ -7,7 +7,7 @@ export const MULTILANG_GROUP_FIELD = DEFAULT_FIELD_NAMES.group;
7
7
  export const MULTILANG_LANGUAGE_FIELD = DEFAULT_FIELD_NAMES.language;
8
8
  export const MULTILANG_META_FIELD = DEFAULT_FIELD_NAMES.meta;
9
9
  export const DEFAULT_GLOBAL_TABS_LABEL = 'Localized content';
10
- export const DEFAULT_DUPLICATE_EXCLUDE_FIELDS = [
10
+ export const SYSTEM_DUPLICATION_EXCLUDED_FIELDS = [
11
11
  'id',
12
12
  'createdAt',
13
13
  'updatedAt',
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/constants.ts"],"sourcesContent":["import type { MultilangFieldNames } from './types.js'\n\nexport const DEFAULT_FIELD_NAMES: MultilangFieldNames = {\n group: '_multilangGroup',\n language: '_multilangLanguage',\n meta: '_multilangMeta',\n}\n\nexport const MULTILANG_GROUP_FIELD = DEFAULT_FIELD_NAMES.group\nexport const MULTILANG_LANGUAGE_FIELD = DEFAULT_FIELD_NAMES.language\nexport const MULTILANG_META_FIELD = DEFAULT_FIELD_NAMES.meta\n\nexport const DEFAULT_GLOBAL_TABS_LABEL = 'Localized content'\n\nexport const DEFAULT_DUPLICATE_EXCLUDE_FIELDS = [\n 'id',\n 'createdAt',\n 'updatedAt',\n 'deletedAt',\n '_status',\n 'sizes',\n 'filename',\n 'filesize',\n 'height',\n 'mimeType',\n 'thumbnailURL',\n 'url',\n 'width',\n]\n\nexport const MULTILANG_SKIP_HOOK = 'payloadMultilangSkip'\n"],"names":["DEFAULT_FIELD_NAMES","group","language","meta","MULTILANG_GROUP_FIELD","MULTILANG_LANGUAGE_FIELD","MULTILANG_META_FIELD","DEFAULT_GLOBAL_TABS_LABEL","DEFAULT_DUPLICATE_EXCLUDE_FIELDS","MULTILANG_SKIP_HOOK"],"mappings":"AAEA,OAAO,MAAMA,sBAA2C;IACtDC,OAAO;IACPC,UAAU;IACVC,MAAM;AACR,EAAC;AAED,OAAO,MAAMC,wBAAwBJ,oBAAoBC,KAAK,CAAA;AAC9D,OAAO,MAAMI,2BAA2BL,oBAAoBE,QAAQ,CAAA;AACpE,OAAO,MAAMI,uBAAuBN,oBAAoBG,IAAI,CAAA;AAE5D,OAAO,MAAMI,4BAA4B,oBAAmB;AAE5D,OAAO,MAAMC,mCAAmC;IAC9C;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;CACD,CAAA;AAED,OAAO,MAAMC,sBAAsB,uBAAsB"}
1
+ {"version":3,"sources":["../src/constants.ts"],"sourcesContent":["import type { MultilangFieldNames } from './types.js'\n\nexport const DEFAULT_FIELD_NAMES: MultilangFieldNames = {\n group: '_multilangGroup',\n language: '_multilangLanguage',\n meta: '_multilangMeta',\n}\n\nexport const MULTILANG_GROUP_FIELD = DEFAULT_FIELD_NAMES.group\nexport const MULTILANG_LANGUAGE_FIELD = DEFAULT_FIELD_NAMES.language\nexport const MULTILANG_META_FIELD = DEFAULT_FIELD_NAMES.meta\n\nexport const DEFAULT_GLOBAL_TABS_LABEL = 'Localized content'\n\nexport const SYSTEM_DUPLICATION_EXCLUDED_FIELDS = [\n 'id',\n 'createdAt',\n 'updatedAt',\n 'deletedAt',\n '_status',\n 'sizes',\n 'filename',\n 'filesize',\n 'height',\n 'mimeType',\n 'thumbnailURL',\n 'url',\n 'width',\n]\n\nexport const MULTILANG_SKIP_HOOK = 'payloadMultilangSkip'\n"],"names":["DEFAULT_FIELD_NAMES","group","language","meta","MULTILANG_GROUP_FIELD","MULTILANG_LANGUAGE_FIELD","MULTILANG_META_FIELD","DEFAULT_GLOBAL_TABS_LABEL","SYSTEM_DUPLICATION_EXCLUDED_FIELDS","MULTILANG_SKIP_HOOK"],"mappings":"AAEA,OAAO,MAAMA,sBAA2C;IACtDC,OAAO;IACPC,UAAU;IACVC,MAAM;AACR,EAAC;AAED,OAAO,MAAMC,wBAAwBJ,oBAAoBC,KAAK,CAAA;AAC9D,OAAO,MAAMI,2BAA2BL,oBAAoBE,QAAQ,CAAA;AACpE,OAAO,MAAMI,uBAAuBN,oBAAoBG,IAAI,CAAA;AAE5D,OAAO,MAAMI,4BAA4B,oBAAmB;AAE5D,OAAO,MAAMC,qCAAqC;IAChD;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;CACD,CAAA;AAED,OAAO,MAAMC,sBAAsB,uBAAsB"}
@@ -97,15 +97,15 @@ export const createTranslationStateEndpoint = ({ collection })=>({
97
97
  id,
98
98
  collection: collection.slug,
99
99
  fieldNames: collection.fieldNames,
100
- payload: req.payload,
101
100
  overrideAccess: false,
101
+ payload: req.payload,
102
102
  req
103
103
  }) : await getGroupTranslationsWithPayload({
104
104
  collection: collection.slug,
105
105
  fieldNames: collection.fieldNames,
106
106
  group: group,
107
- payload: req.payload,
108
107
  overrideAccess: false,
108
+ payload: req.payload,
109
109
  req
110
110
  });
111
111
  return json(state);
@@ -153,14 +153,12 @@ export const createCreateTranslationEndpoint = ({ collection, collectionConfig }
153
153
  if (duplicateError) {
154
154
  return duplicateError;
155
155
  }
156
- const shouldDuplicate = body.duplicate !== false && collection.duplicate;
157
- const data = shouldDuplicate ? duplicateDocumentData({
156
+ const data = duplicateDocumentData({
158
157
  collection: collectionConfig,
159
158
  doc: source,
160
- duplicateExcludeFields: collection.duplicateExcludeFields,
161
159
  fieldNames: collection.fieldNames,
162
160
  targetLanguage
163
- }) : {};
161
+ });
164
162
  const doc = await req.payload.create({
165
163
  collection: collection.slug,
166
164
  data: {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/endpoints/translations.ts"],"sourcesContent":["import type { CollectionConfig, Endpoint, PayloadRequest, Where } from 'payload'\n\nimport { randomUUID } from 'crypto'\n\nimport type { ResolvedMultilangCollection } from '../types.js'\n\nimport { MULTILANG_SKIP_HOOK } from '../constants.js'\nimport {\n asDocument,\n duplicateDocumentData,\n getDocumentTranslationsWithPayload,\n getGroupTranslationsWithPayload,\n getID,\n getStringValue,\n} from '../lib/data.js'\n\nconst json = (body: unknown, init?: ResponseInit): Response =>\n Response.json(body, init)\n\nconst parseBody = async (req: PayloadRequest): Promise<Record<string, unknown>> => {\n if (typeof req.json !== 'function') {\n return {}\n }\n\n return asDocument(await req.json())\n}\n\nconst getLanguageCode = (value: unknown): string | undefined => {\n const language = getStringValue(value)?.trim().toLowerCase()\n\n return language || undefined\n}\n\nconst validateLanguage = ({\n collection,\n language,\n}: {\n collection: ResolvedMultilangCollection\n language: string\n}): Response | undefined => {\n if (collection.languages.some((candidate) => candidate.code === language)) {\n return undefined\n }\n\n return json(\n {\n message: `Language \"${language}\" is not configured for ${collection.slug}.`,\n },\n { status: 400 },\n )\n}\n\nconst ensureGroup = async ({\n collection,\n doc,\n req,\n}: {\n collection: ResolvedMultilangCollection\n doc: Record<string, unknown>\n req: PayloadRequest\n}): Promise<string> => {\n const existingGroup = getStringValue(doc[collection.fieldNames.group])\n\n if (existingGroup) {\n return existingGroup\n }\n\n const id = getID(doc.id)\n\n if (!id) {\n return randomUUID()\n }\n\n const group = randomUUID()\n\n await req.payload.update({\n id,\n collection: collection.slug,\n context: {\n [MULTILANG_SKIP_HOOK]: true,\n },\n data: {\n [collection.fieldNames.group]: group,\n },\n overrideAccess: false,\n req,\n })\n\n return group\n}\n\nconst checkDuplicateLanguage = async ({\n collection,\n excludeID,\n group,\n language,\n req,\n}: {\n collection: ResolvedMultilangCollection\n excludeID?: number | string\n group: string\n language: string\n req: PayloadRequest\n}): Promise<Response | undefined> => {\n const and: Where[] = [\n {\n [collection.fieldNames.group]: {\n equals: group,\n },\n },\n {\n [collection.fieldNames.language]: {\n equals: language,\n },\n },\n ]\n\n if (excludeID) {\n and.push({\n id: {\n not_equals: excludeID,\n },\n })\n }\n\n const { totalDocs } = await req.payload.count({\n collection: collection.slug,\n overrideAccess: false,\n req,\n where: {\n and,\n },\n })\n\n if (totalDocs > 0) {\n return json(\n {\n message: `A translation already exists for language \"${language}\".`,\n },\n { status: 409 },\n )\n }\n}\n\nexport const createTranslationStateEndpoint = ({\n collection,\n}: {\n collection: ResolvedMultilangCollection\n}): Endpoint => ({\n handler: async (req) => {\n const id = getID(req.query?.id)\n const group = getStringValue(req.query?.group)\n\n if (!id && !group) {\n return json({ message: 'Missing document id or translation group.' }, { status: 400 })\n }\n\n const state = id\n ? await getDocumentTranslationsWithPayload({\n id,\n collection: collection.slug,\n fieldNames: collection.fieldNames,\n payload: req.payload,\n overrideAccess: false,\n req,\n })\n : await getGroupTranslationsWithPayload({\n collection: collection.slug,\n fieldNames: collection.fieldNames,\n group: group!,\n payload: req.payload,\n overrideAccess: false,\n req,\n })\n\n return json(state)\n },\n method: 'get',\n path: '/multilang/state',\n})\n\nexport const createCreateTranslationEndpoint = ({\n collection,\n collectionConfig,\n}: {\n collection: ResolvedMultilangCollection\n collectionConfig: CollectionConfig\n}): Endpoint => ({\n handler: async (req) => {\n const body = await parseBody(req)\n const sourceID = getID(body.sourceId)\n const targetLanguage = getLanguageCode(body.targetLanguage)\n\n if (!sourceID || !targetLanguage) {\n return json(\n { message: 'sourceId and targetLanguage are required.' },\n { status: 400 },\n )\n }\n\n const languageError = validateLanguage({\n collection,\n language: targetLanguage,\n })\n\n if (languageError) {\n return languageError\n }\n\n const source = asDocument(\n await req.payload.findByID({\n id: sourceID,\n collection: collection.slug,\n depth: 0,\n overrideAccess: false,\n req,\n }),\n )\n const group = await ensureGroup({ collection, doc: source, req })\n const duplicateError = await checkDuplicateLanguage({\n collection,\n group,\n language: targetLanguage,\n req,\n })\n\n if (duplicateError) {\n return duplicateError\n }\n\n const shouldDuplicate = body.duplicate !== false && collection.duplicate\n const data = shouldDuplicate\n ? duplicateDocumentData({\n collection: collectionConfig,\n doc: source,\n duplicateExcludeFields: collection.duplicateExcludeFields,\n fieldNames: collection.fieldNames,\n targetLanguage,\n })\n : {}\n\n const doc = await req.payload.create({\n collection: collection.slug,\n data: {\n ...data,\n [collection.fieldNames.group]: group,\n [collection.fieldNames.language]: targetLanguage,\n [collection.fieldNames.meta]: {\n createdFrom: sourceID,\n },\n },\n overrideAccess: false,\n req,\n })\n\n return json({\n doc,\n })\n },\n method: 'post',\n path: '/multilang/create',\n})\n\nexport const createConnectTranslationEndpoint = ({\n collection,\n}: {\n collection: ResolvedMultilangCollection\n}): Endpoint => ({\n handler: async (req) => {\n const body = await parseBody(req)\n const sourceID = getID(body.sourceId)\n const targetID = getID(body.targetId)\n const targetLanguage = getLanguageCode(body.targetLanguage)\n\n if (!sourceID || !targetID || sourceID === targetID) {\n return json({ message: 'sourceId and a different targetId are required.' }, { status: 400 })\n }\n\n const source = asDocument(\n await req.payload.findByID({\n id: sourceID,\n collection: collection.slug,\n depth: 0,\n overrideAccess: false,\n req,\n }),\n )\n const target = asDocument(\n await req.payload.findByID({\n id: targetID,\n collection: collection.slug,\n depth: 0,\n overrideAccess: false,\n req,\n }),\n )\n const group = await ensureGroup({ collection, doc: source, req })\n const language =\n targetLanguage ||\n getLanguageCode(target[collection.fieldNames.language]) ||\n getLanguageCode(source[collection.fieldNames.language])\n\n if (!language) {\n return json({ message: 'Target language is required.' }, { status: 400 })\n }\n\n const languageError = validateLanguage({\n collection,\n language,\n })\n\n if (languageError) {\n return languageError\n }\n\n const duplicateError = await checkDuplicateLanguage({\n collection,\n excludeID: targetID,\n group,\n language,\n req,\n })\n\n if (duplicateError) {\n return duplicateError\n }\n\n const doc = await req.payload.update({\n id: targetID,\n collection: collection.slug,\n data: {\n [collection.fieldNames.group]: group,\n [collection.fieldNames.language]: language,\n },\n overrideAccess: false,\n req,\n })\n\n return json({ doc })\n },\n method: 'post',\n path: '/multilang/connect',\n})\n\nexport const createDisconnectTranslationEndpoint = ({\n collection,\n}: {\n collection: ResolvedMultilangCollection\n}): Endpoint => ({\n handler: async (req) => {\n const body = await parseBody(req)\n const id = getID(body.id)\n\n if (!id) {\n return json({ message: 'Missing document id.' }, { status: 400 })\n }\n\n const doc = await req.payload.update({\n id,\n collection: collection.slug,\n data: {\n [collection.fieldNames.group]: randomUUID(),\n },\n overrideAccess: false,\n req,\n })\n\n return json({ doc })\n },\n method: 'post',\n path: '/multilang/disconnect',\n})\n\nexport const createTranslationEndpoints = ({\n collection,\n collectionConfig,\n}: {\n collection: ResolvedMultilangCollection\n collectionConfig: CollectionConfig\n}): Endpoint[] => [\n createTranslationStateEndpoint({ collection }),\n createCreateTranslationEndpoint({ collection, collectionConfig }),\n createConnectTranslationEndpoint({ collection }),\n createDisconnectTranslationEndpoint({ collection }),\n]\n"],"names":["randomUUID","MULTILANG_SKIP_HOOK","asDocument","duplicateDocumentData","getDocumentTranslationsWithPayload","getGroupTranslationsWithPayload","getID","getStringValue","json","body","init","Response","parseBody","req","getLanguageCode","value","language","trim","toLowerCase","undefined","validateLanguage","collection","languages","some","candidate","code","message","slug","status","ensureGroup","doc","existingGroup","fieldNames","group","id","payload","update","context","data","overrideAccess","checkDuplicateLanguage","excludeID","and","equals","push","not_equals","totalDocs","count","where","createTranslationStateEndpoint","handler","query","state","method","path","createCreateTranslationEndpoint","collectionConfig","sourceID","sourceId","targetLanguage","languageError","source","findByID","depth","duplicateError","shouldDuplicate","duplicate","duplicateExcludeFields","create","meta","createdFrom","createConnectTranslationEndpoint","targetID","targetId","target","createDisconnectTranslationEndpoint","createTranslationEndpoints"],"mappings":"AAEA,SAASA,UAAU,QAAQ,SAAQ;AAInC,SAASC,mBAAmB,QAAQ,kBAAiB;AACrD,SACEC,UAAU,EACVC,qBAAqB,EACrBC,kCAAkC,EAClCC,+BAA+B,EAC/BC,KAAK,EACLC,cAAc,QACT,iBAAgB;AAEvB,MAAMC,OAAO,CAACC,MAAeC,OAC3BC,SAASH,IAAI,CAACC,MAAMC;AAEtB,MAAME,YAAY,OAAOC;IACvB,IAAI,OAAOA,IAAIL,IAAI,KAAK,YAAY;QAClC,OAAO,CAAC;IACV;IAEA,OAAON,WAAW,MAAMW,IAAIL,IAAI;AAClC;AAEA,MAAMM,kBAAkB,CAACC;IACvB,MAAMC,WAAWT,eAAeQ,QAAQE,OAAOC;IAE/C,OAAOF,YAAYG;AACrB;AAEA,MAAMC,mBAAmB,CAAC,EACxBC,UAAU,EACVL,QAAQ,EAIT;IACC,IAAIK,WAAWC,SAAS,CAACC,IAAI,CAAC,CAACC,YAAcA,UAAUC,IAAI,KAAKT,WAAW;QACzE,OAAOG;IACT;IAEA,OAAOX,KACL;QACEkB,SAAS,CAAC,UAAU,EAAEV,SAAS,wBAAwB,EAAEK,WAAWM,IAAI,CAAC,CAAC,CAAC;IAC7E,GACA;QAAEC,QAAQ;IAAI;AAElB;AAEA,MAAMC,cAAc,OAAO,EACzBR,UAAU,EACVS,GAAG,EACHjB,GAAG,EAKJ;IACC,MAAMkB,gBAAgBxB,eAAeuB,GAAG,CAACT,WAAWW,UAAU,CAACC,KAAK,CAAC;IAErE,IAAIF,eAAe;QACjB,OAAOA;IACT;IAEA,MAAMG,KAAK5B,MAAMwB,IAAII,EAAE;IAEvB,IAAI,CAACA,IAAI;QACP,OAAOlC;IACT;IAEA,MAAMiC,QAAQjC;IAEd,MAAMa,IAAIsB,OAAO,CAACC,MAAM,CAAC;QACvBF;QACAb,YAAYA,WAAWM,IAAI;QAC3BU,SAAS;YACP,CAACpC,oBAAoB,EAAE;QACzB;QACAqC,MAAM;YACJ,CAACjB,WAAWW,UAAU,CAACC,KAAK,CAAC,EAAEA;QACjC;QACAM,gBAAgB;QAChB1B;IACF;IAEA,OAAOoB;AACT;AAEA,MAAMO,yBAAyB,OAAO,EACpCnB,UAAU,EACVoB,SAAS,EACTR,KAAK,EACLjB,QAAQ,EACRH,GAAG,EAOJ;IACC,MAAM6B,MAAe;QACnB;YACE,CAACrB,WAAWW,UAAU,CAACC,KAAK,CAAC,EAAE;gBAC7BU,QAAQV;YACV;QACF;QACA;YACE,CAACZ,WAAWW,UAAU,CAAChB,QAAQ,CAAC,EAAE;gBAChC2B,QAAQ3B;YACV;QACF;KACD;IAED,IAAIyB,WAAW;QACbC,IAAIE,IAAI,CAAC;YACPV,IAAI;gBACFW,YAAYJ;YACd;QACF;IACF;IAEA,MAAM,EAAEK,SAAS,EAAE,GAAG,MAAMjC,IAAIsB,OAAO,CAACY,KAAK,CAAC;QAC5C1B,YAAYA,WAAWM,IAAI;QAC3BY,gBAAgB;QAChB1B;QACAmC,OAAO;YACLN;QACF;IACF;IAEA,IAAII,YAAY,GAAG;QACjB,OAAOtC,KACL;YACEkB,SAAS,CAAC,2CAA2C,EAAEV,SAAS,EAAE,CAAC;QACrE,GACA;YAAEY,QAAQ;QAAI;IAElB;AACF;AAEA,OAAO,MAAMqB,iCAAiC,CAAC,EAC7C5B,UAAU,EAGX,GAAgB,CAAA;QACf6B,SAAS,OAAOrC;YACd,MAAMqB,KAAK5B,MAAMO,IAAIsC,KAAK,EAAEjB;YAC5B,MAAMD,QAAQ1B,eAAeM,IAAIsC,KAAK,EAAElB;YAExC,IAAI,CAACC,MAAM,CAACD,OAAO;gBACjB,OAAOzB,KAAK;oBAAEkB,SAAS;gBAA4C,GAAG;oBAAEE,QAAQ;gBAAI;YACtF;YAEA,MAAMwB,QAAQlB,KACV,MAAM9B,mCAAmC;gBACvC8B;gBACAb,YAAYA,WAAWM,IAAI;gBAC3BK,YAAYX,WAAWW,UAAU;gBACjCG,SAAStB,IAAIsB,OAAO;gBACpBI,gBAAgB;gBAChB1B;YACF,KACA,MAAMR,gCAAgC;gBACpCgB,YAAYA,WAAWM,IAAI;gBAC3BK,YAAYX,WAAWW,UAAU;gBACjCC,OAAOA;gBACPE,SAAStB,IAAIsB,OAAO;gBACpBI,gBAAgB;gBAChB1B;YACF;YAEJ,OAAOL,KAAK4C;QACd;QACAC,QAAQ;QACRC,MAAM;IACR,CAAA,EAAE;AAEF,OAAO,MAAMC,kCAAkC,CAAC,EAC9ClC,UAAU,EACVmC,gBAAgB,EAIjB,GAAgB,CAAA;QACfN,SAAS,OAAOrC;YACd,MAAMJ,OAAO,MAAMG,UAAUC;YAC7B,MAAM4C,WAAWnD,MAAMG,KAAKiD,QAAQ;YACpC,MAAMC,iBAAiB7C,gBAAgBL,KAAKkD,cAAc;YAE1D,IAAI,CAACF,YAAY,CAACE,gBAAgB;gBAChC,OAAOnD,KACL;oBAAEkB,SAAS;gBAA4C,GACvD;oBAAEE,QAAQ;gBAAI;YAElB;YAEA,MAAMgC,gBAAgBxC,iBAAiB;gBACrCC;gBACAL,UAAU2C;YACZ;YAEA,IAAIC,eAAe;gBACjB,OAAOA;YACT;YAEA,MAAMC,SAAS3D,WACb,MAAMW,IAAIsB,OAAO,CAAC2B,QAAQ,CAAC;gBACzB5B,IAAIuB;gBACJpC,YAAYA,WAAWM,IAAI;gBAC3BoC,OAAO;gBACPxB,gBAAgB;gBAChB1B;YACF;YAEF,MAAMoB,QAAQ,MAAMJ,YAAY;gBAAER;gBAAYS,KAAK+B;gBAAQhD;YAAI;YAC/D,MAAMmD,iBAAiB,MAAMxB,uBAAuB;gBAClDnB;gBACAY;gBACAjB,UAAU2C;gBACV9C;YACF;YAEA,IAAImD,gBAAgB;gBAClB,OAAOA;YACT;YAEA,MAAMC,kBAAkBxD,KAAKyD,SAAS,KAAK,SAAS7C,WAAW6C,SAAS;YACxE,MAAM5B,OAAO2B,kBACT9D,sBAAsB;gBACpBkB,YAAYmC;gBACZ1B,KAAK+B;gBACLM,wBAAwB9C,WAAW8C,sBAAsB;gBACzDnC,YAAYX,WAAWW,UAAU;gBACjC2B;YACF,KACA,CAAC;YAEL,MAAM7B,MAAM,MAAMjB,IAAIsB,OAAO,CAACiC,MAAM,CAAC;gBACnC/C,YAAYA,WAAWM,IAAI;gBAC3BW,MAAM;oBACJ,GAAGA,IAAI;oBACP,CAACjB,WAAWW,UAAU,CAACC,KAAK,CAAC,EAAEA;oBAC/B,CAACZ,WAAWW,UAAU,CAAChB,QAAQ,CAAC,EAAE2C;oBAClC,CAACtC,WAAWW,UAAU,CAACqC,IAAI,CAAC,EAAE;wBAC5BC,aAAab;oBACf;gBACF;gBACAlB,gBAAgB;gBAChB1B;YACF;YAEA,OAAOL,KAAK;gBACVsB;YACF;QACF;QACAuB,QAAQ;QACRC,MAAM;IACR,CAAA,EAAE;AAEF,OAAO,MAAMiB,mCAAmC,CAAC,EAC/ClD,UAAU,EAGX,GAAgB,CAAA;QACf6B,SAAS,OAAOrC;YACd,MAAMJ,OAAO,MAAMG,UAAUC;YAC7B,MAAM4C,WAAWnD,MAAMG,KAAKiD,QAAQ;YACpC,MAAMc,WAAWlE,MAAMG,KAAKgE,QAAQ;YACpC,MAAMd,iBAAiB7C,gBAAgBL,KAAKkD,cAAc;YAE1D,IAAI,CAACF,YAAY,CAACe,YAAYf,aAAae,UAAU;gBACnD,OAAOhE,KAAK;oBAAEkB,SAAS;gBAAkD,GAAG;oBAAEE,QAAQ;gBAAI;YAC5F;YAEA,MAAMiC,SAAS3D,WACb,MAAMW,IAAIsB,OAAO,CAAC2B,QAAQ,CAAC;gBACzB5B,IAAIuB;gBACJpC,YAAYA,WAAWM,IAAI;gBAC3BoC,OAAO;gBACPxB,gBAAgB;gBAChB1B;YACF;YAEF,MAAM6D,SAASxE,WACb,MAAMW,IAAIsB,OAAO,CAAC2B,QAAQ,CAAC;gBACzB5B,IAAIsC;gBACJnD,YAAYA,WAAWM,IAAI;gBAC3BoC,OAAO;gBACPxB,gBAAgB;gBAChB1B;YACF;YAEF,MAAMoB,QAAQ,MAAMJ,YAAY;gBAAER;gBAAYS,KAAK+B;gBAAQhD;YAAI;YAC/D,MAAMG,WACJ2C,kBACA7C,gBAAgB4D,MAAM,CAACrD,WAAWW,UAAU,CAAChB,QAAQ,CAAC,KACtDF,gBAAgB+C,MAAM,CAACxC,WAAWW,UAAU,CAAChB,QAAQ,CAAC;YAExD,IAAI,CAACA,UAAU;gBACb,OAAOR,KAAK;oBAAEkB,SAAS;gBAA+B,GAAG;oBAAEE,QAAQ;gBAAI;YACzE;YAEA,MAAMgC,gBAAgBxC,iBAAiB;gBACrCC;gBACAL;YACF;YAEA,IAAI4C,eAAe;gBACjB,OAAOA;YACT;YAEA,MAAMI,iBAAiB,MAAMxB,uBAAuB;gBAClDnB;gBACAoB,WAAW+B;gBACXvC;gBACAjB;gBACAH;YACF;YAEA,IAAImD,gBAAgB;gBAClB,OAAOA;YACT;YAEA,MAAMlC,MAAM,MAAMjB,IAAIsB,OAAO,CAACC,MAAM,CAAC;gBACnCF,IAAIsC;gBACJnD,YAAYA,WAAWM,IAAI;gBAC3BW,MAAM;oBACJ,CAACjB,WAAWW,UAAU,CAACC,KAAK,CAAC,EAAEA;oBAC/B,CAACZ,WAAWW,UAAU,CAAChB,QAAQ,CAAC,EAAEA;gBACpC;gBACAuB,gBAAgB;gBAChB1B;YACF;YAEA,OAAOL,KAAK;gBAAEsB;YAAI;QACpB;QACAuB,QAAQ;QACRC,MAAM;IACR,CAAA,EAAE;AAEF,OAAO,MAAMqB,sCAAsC,CAAC,EAClDtD,UAAU,EAGX,GAAgB,CAAA;QACf6B,SAAS,OAAOrC;YACd,MAAMJ,OAAO,MAAMG,UAAUC;YAC7B,MAAMqB,KAAK5B,MAAMG,KAAKyB,EAAE;YAExB,IAAI,CAACA,IAAI;gBACP,OAAO1B,KAAK;oBAAEkB,SAAS;gBAAuB,GAAG;oBAAEE,QAAQ;gBAAI;YACjE;YAEA,MAAME,MAAM,MAAMjB,IAAIsB,OAAO,CAACC,MAAM,CAAC;gBACnCF;gBACAb,YAAYA,WAAWM,IAAI;gBAC3BW,MAAM;oBACJ,CAACjB,WAAWW,UAAU,CAACC,KAAK,CAAC,EAAEjC;gBACjC;gBACAuC,gBAAgB;gBAChB1B;YACF;YAEA,OAAOL,KAAK;gBAAEsB;YAAI;QACpB;QACAuB,QAAQ;QACRC,MAAM;IACR,CAAA,EAAE;AAEF,OAAO,MAAMsB,6BAA6B,CAAC,EACzCvD,UAAU,EACVmC,gBAAgB,EAIjB,GAAiB;QAChBP,+BAA+B;YAAE5B;QAAW;QAC5CkC,gCAAgC;YAAElC;YAAYmC;QAAiB;QAC/De,iCAAiC;YAAElD;QAAW;QAC9CsD,oCAAoC;YAAEtD;QAAW;KAClD,CAAA"}
1
+ {"version":3,"sources":["../../src/endpoints/translations.ts"],"sourcesContent":["import type { CollectionConfig, Endpoint, PayloadRequest, Where } from 'payload'\n\nimport { randomUUID } from 'crypto'\n\nimport type { ResolvedMultilangCollection } from '../types.js'\n\nimport { MULTILANG_SKIP_HOOK } from '../constants.js'\nimport {\n asDocument,\n duplicateDocumentData,\n getDocumentTranslationsWithPayload,\n getGroupTranslationsWithPayload,\n getID,\n getStringValue,\n} from '../lib/data.js'\n\nconst json = (body: unknown, init?: ResponseInit): Response =>\n Response.json(body, init)\n\nconst parseBody = async (req: PayloadRequest): Promise<Record<string, unknown>> => {\n if (typeof req.json !== 'function') {\n return {}\n }\n\n return asDocument(await req.json())\n}\n\nconst getLanguageCode = (value: unknown): string | undefined => {\n const language = getStringValue(value)?.trim().toLowerCase()\n\n return language || undefined\n}\n\nconst validateLanguage = ({\n collection,\n language,\n}: {\n collection: ResolvedMultilangCollection\n language: string\n}): Response | undefined => {\n if (collection.languages.some((candidate) => candidate.code === language)) {\n return undefined\n }\n\n return json(\n {\n message: `Language \"${language}\" is not configured for ${collection.slug}.`,\n },\n { status: 400 },\n )\n}\n\nconst ensureGroup = async ({\n collection,\n doc,\n req,\n}: {\n collection: ResolvedMultilangCollection\n doc: Record<string, unknown>\n req: PayloadRequest\n}): Promise<string> => {\n const existingGroup = getStringValue(doc[collection.fieldNames.group])\n\n if (existingGroup) {\n return existingGroup\n }\n\n const id = getID(doc.id)\n\n if (!id) {\n return randomUUID()\n }\n\n const group = randomUUID()\n\n await req.payload.update({\n id,\n collection: collection.slug,\n context: {\n [MULTILANG_SKIP_HOOK]: true,\n },\n data: {\n [collection.fieldNames.group]: group,\n },\n overrideAccess: false,\n req,\n })\n\n return group\n}\n\nconst checkDuplicateLanguage = async ({\n collection,\n excludeID,\n group,\n language,\n req,\n}: {\n collection: ResolvedMultilangCollection\n excludeID?: number | string\n group: string\n language: string\n req: PayloadRequest\n}): Promise<Response | undefined> => {\n const and: Where[] = [\n {\n [collection.fieldNames.group]: {\n equals: group,\n },\n },\n {\n [collection.fieldNames.language]: {\n equals: language,\n },\n },\n ]\n\n if (excludeID) {\n and.push({\n id: {\n not_equals: excludeID,\n },\n })\n }\n\n const { totalDocs } = await req.payload.count({\n collection: collection.slug,\n overrideAccess: false,\n req,\n where: {\n and,\n },\n })\n\n if (totalDocs > 0) {\n return json(\n {\n message: `A translation already exists for language \"${language}\".`,\n },\n { status: 409 },\n )\n }\n}\n\nexport const createTranslationStateEndpoint = ({\n collection,\n}: {\n collection: ResolvedMultilangCollection\n}): Endpoint => ({\n handler: async (req) => {\n const id = getID(req.query?.id)\n const group = getStringValue(req.query?.group)\n\n if (!id && !group) {\n return json({ message: 'Missing document id or translation group.' }, { status: 400 })\n }\n\n const state = id\n ? await getDocumentTranslationsWithPayload({\n id,\n collection: collection.slug,\n fieldNames: collection.fieldNames,\n overrideAccess: false,\n payload: req.payload,\n req,\n })\n : await getGroupTranslationsWithPayload({\n collection: collection.slug,\n fieldNames: collection.fieldNames,\n group: group!,\n overrideAccess: false,\n payload: req.payload,\n req,\n })\n\n return json(state)\n },\n method: 'get',\n path: '/multilang/state',\n})\n\nexport const createCreateTranslationEndpoint = ({\n collection,\n collectionConfig,\n}: {\n collection: ResolvedMultilangCollection\n collectionConfig: CollectionConfig\n}): Endpoint => ({\n handler: async (req) => {\n const body = await parseBody(req)\n const sourceID = getID(body.sourceId)\n const targetLanguage = getLanguageCode(body.targetLanguage)\n\n if (!sourceID || !targetLanguage) {\n return json(\n { message: 'sourceId and targetLanguage are required.' },\n { status: 400 },\n )\n }\n\n const languageError = validateLanguage({\n collection,\n language: targetLanguage,\n })\n\n if (languageError) {\n return languageError\n }\n\n const source = asDocument(\n await req.payload.findByID({\n id: sourceID,\n collection: collection.slug,\n depth: 0,\n overrideAccess: false,\n req,\n }),\n )\n const group = await ensureGroup({ collection, doc: source, req })\n const duplicateError = await checkDuplicateLanguage({\n collection,\n group,\n language: targetLanguage,\n req,\n })\n\n if (duplicateError) {\n return duplicateError\n }\n\n const data = duplicateDocumentData({\n collection: collectionConfig,\n doc: source,\n fieldNames: collection.fieldNames,\n targetLanguage,\n })\n\n const doc = await req.payload.create({\n collection: collection.slug,\n data: {\n ...data,\n [collection.fieldNames.group]: group,\n [collection.fieldNames.language]: targetLanguage,\n [collection.fieldNames.meta]: {\n createdFrom: sourceID,\n },\n },\n overrideAccess: false,\n req,\n })\n\n return json({\n doc,\n })\n },\n method: 'post',\n path: '/multilang/create',\n})\n\nexport const createConnectTranslationEndpoint = ({\n collection,\n}: {\n collection: ResolvedMultilangCollection\n}): Endpoint => ({\n handler: async (req) => {\n const body = await parseBody(req)\n const sourceID = getID(body.sourceId)\n const targetID = getID(body.targetId)\n const targetLanguage = getLanguageCode(body.targetLanguage)\n\n if (!sourceID || !targetID || sourceID === targetID) {\n return json({ message: 'sourceId and a different targetId are required.' }, { status: 400 })\n }\n\n const source = asDocument(\n await req.payload.findByID({\n id: sourceID,\n collection: collection.slug,\n depth: 0,\n overrideAccess: false,\n req,\n }),\n )\n const target = asDocument(\n await req.payload.findByID({\n id: targetID,\n collection: collection.slug,\n depth: 0,\n overrideAccess: false,\n req,\n }),\n )\n const group = await ensureGroup({ collection, doc: source, req })\n const language =\n targetLanguage ||\n getLanguageCode(target[collection.fieldNames.language]) ||\n getLanguageCode(source[collection.fieldNames.language])\n\n if (!language) {\n return json({ message: 'Target language is required.' }, { status: 400 })\n }\n\n const languageError = validateLanguage({\n collection,\n language,\n })\n\n if (languageError) {\n return languageError\n }\n\n const duplicateError = await checkDuplicateLanguage({\n collection,\n excludeID: targetID,\n group,\n language,\n req,\n })\n\n if (duplicateError) {\n return duplicateError\n }\n\n const doc = await req.payload.update({\n id: targetID,\n collection: collection.slug,\n data: {\n [collection.fieldNames.group]: group,\n [collection.fieldNames.language]: language,\n },\n overrideAccess: false,\n req,\n })\n\n return json({ doc })\n },\n method: 'post',\n path: '/multilang/connect',\n})\n\nexport const createDisconnectTranslationEndpoint = ({\n collection,\n}: {\n collection: ResolvedMultilangCollection\n}): Endpoint => ({\n handler: async (req) => {\n const body = await parseBody(req)\n const id = getID(body.id)\n\n if (!id) {\n return json({ message: 'Missing document id.' }, { status: 400 })\n }\n\n const doc = await req.payload.update({\n id,\n collection: collection.slug,\n data: {\n [collection.fieldNames.group]: randomUUID(),\n },\n overrideAccess: false,\n req,\n })\n\n return json({ doc })\n },\n method: 'post',\n path: '/multilang/disconnect',\n})\n\nexport const createTranslationEndpoints = ({\n collection,\n collectionConfig,\n}: {\n collection: ResolvedMultilangCollection\n collectionConfig: CollectionConfig\n}): Endpoint[] => [\n createTranslationStateEndpoint({ collection }),\n createCreateTranslationEndpoint({ collection, collectionConfig }),\n createConnectTranslationEndpoint({ collection }),\n createDisconnectTranslationEndpoint({ collection }),\n]\n"],"names":["randomUUID","MULTILANG_SKIP_HOOK","asDocument","duplicateDocumentData","getDocumentTranslationsWithPayload","getGroupTranslationsWithPayload","getID","getStringValue","json","body","init","Response","parseBody","req","getLanguageCode","value","language","trim","toLowerCase","undefined","validateLanguage","collection","languages","some","candidate","code","message","slug","status","ensureGroup","doc","existingGroup","fieldNames","group","id","payload","update","context","data","overrideAccess","checkDuplicateLanguage","excludeID","and","equals","push","not_equals","totalDocs","count","where","createTranslationStateEndpoint","handler","query","state","method","path","createCreateTranslationEndpoint","collectionConfig","sourceID","sourceId","targetLanguage","languageError","source","findByID","depth","duplicateError","create","meta","createdFrom","createConnectTranslationEndpoint","targetID","targetId","target","createDisconnectTranslationEndpoint","createTranslationEndpoints"],"mappings":"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"}
@@ -3,8 +3,9 @@ import type { ResolvedMultilangCollection } from '../types.js';
3
3
  export declare const createTranslatedCollectionBeforeChangeHook: ({ collection }: {
4
4
  collection: ResolvedMultilangCollection;
5
5
  }) => CollectionBeforeChangeHook;
6
- export declare const createSynchronizedFieldsAfterChangeHook: ({ collection }: {
6
+ export declare const createSynchronizedFieldsAfterChangeHook: ({ collection, fields, }: {
7
7
  collection: ResolvedMultilangCollection;
8
+ fields?: Field[];
8
9
  }) => CollectionAfterChangeHook;
9
10
  export declare const createHiddenFields: ({ collection, }: {
10
11
  collection: ResolvedMultilangCollection;