@roxxel/payload-multilang 0.0.4 → 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.
Files changed (43) hide show
  1. package/LICENSE.md +7 -0
  2. package/README.md +50 -14
  3. package/dist/components/LanguageListToolbar.js +4 -3
  4. package/dist/components/LanguageListToolbar.js.map +1 -1
  5. package/dist/components/LanguageMetabox.js +18 -17
  6. package/dist/components/LanguageMetabox.js.map +1 -1
  7. package/dist/components/TranslationActionsClient.js +16 -14
  8. package/dist/components/TranslationActionsClient.js.map +1 -1
  9. package/dist/components/TranslationColumnCell.js +4 -1
  10. package/dist/components/TranslationColumnCell.js.map +1 -1
  11. package/dist/components/TranslationColumnCellClient.js +16 -7
  12. package/dist/components/TranslationColumnCellClient.js.map +1 -1
  13. package/dist/components/TranslationsTab.js +9 -8
  14. package/dist/components/TranslationsTab.js.map +1 -1
  15. package/dist/constants.d.ts +4 -1
  16. package/dist/constants.js +4 -1
  17. package/dist/constants.js.map +1 -1
  18. package/dist/endpoints/translations.js +4 -6
  19. package/dist/endpoints/translations.js.map +1 -1
  20. package/dist/hooks/translatedCollection.d.ts +2 -1
  21. package/dist/hooks/translatedCollection.js +122 -15
  22. package/dist/hooks/translatedCollection.js.map +1 -1
  23. package/dist/hooks/translatedGlobal.js +5 -1
  24. package/dist/hooks/translatedGlobal.js.map +1 -1
  25. package/dist/index.d.ts +4 -1
  26. package/dist/index.js +27 -3
  27. package/dist/index.js.map +1 -1
  28. package/dist/lib/config.js +2 -10
  29. package/dist/lib/config.js.map +1 -1
  30. package/dist/lib/data.d.ts +72 -35
  31. package/dist/lib/data.js +118 -60
  32. package/dist/lib/data.js.map +1 -1
  33. package/dist/translations.d.ts +72 -0
  34. package/dist/translations.js +72 -0
  35. package/dist/translations.js.map +1 -0
  36. package/dist/types.d.ts +0 -19
  37. package/dist/types.js.map +1 -1
  38. package/docs/configuration.md +75 -10
  39. package/docs/helpers.md +95 -121
  40. package/docs/usage.md +115 -120
  41. package/package.json +1 -1
  42. package/dist/payload-config.d.js +0 -2
  43. package/dist/payload-config.d.js.map +0 -1
package/LICENSE.md ADDED
@@ -0,0 +1,7 @@
1
+ Copyright 2026 Roxxel
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
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
@@ -97,13 +110,14 @@ const posts = await payload.find({
97
110
 
98
111
  ## Translation Helpers
99
112
 
113
+ In request-scoped code, use the `WithPayload` helpers with `req.payload`.
114
+
100
115
  ```ts
101
116
  import {
102
- findGlobalByLanguage,
103
- getDocumentTranslation,
104
- getDocumentTranslations,
105
- getLanguages,
106
- updateGlobalByLanguage,
117
+ findGlobalByLanguageWithPayload,
118
+ getDocumentTranslationWithPayload,
119
+ getDocumentTranslationsWithPayload,
120
+ updateGlobalByLanguageWithPayload,
107
121
  withLanguage,
108
122
  } from '@roxxel/payload-multilang'
109
123
  ```
@@ -111,33 +125,55 @@ import {
111
125
  Common examples:
112
126
 
113
127
  ```ts
114
- const languages = await getLanguages()
115
-
116
- const state = await getDocumentTranslations({
128
+ const state = await getDocumentTranslationsWithPayload({
117
129
  collection: 'posts',
118
130
  id: post.id,
131
+ payload: req.payload,
132
+ req,
133
+ overrideAccess: false,
119
134
  })
120
135
 
121
- const ukrainianPost = await getDocumentTranslation({
136
+ const ukrainianPost = await getDocumentTranslationWithPayload({
122
137
  collection: 'posts',
123
138
  id: post.id,
124
139
  language: 'uk',
140
+ payload: req.payload,
141
+ req,
142
+ overrideAccess: false,
125
143
  })
126
144
 
127
- const settings = await findGlobalByLanguage({
145
+ const settings = await findGlobalByLanguageWithPayload({
128
146
  slug: 'site-settings',
129
147
  language: 'uk',
148
+ payload: req.payload,
149
+ req,
150
+ overrideAccess: false,
130
151
  })
131
152
 
132
- await updateGlobalByLanguage({
153
+ await updateGlobalByLanguageWithPayload({
133
154
  slug: 'site-settings',
134
155
  language: 'uk',
156
+ payload: req.payload,
157
+ req,
158
+ overrideAccess: false,
135
159
  data: {
136
160
  title: 'Localized title',
137
161
  },
138
162
  })
139
163
  ```
140
164
 
165
+ For app-level convenience, create your own configured helper module:
166
+
167
+ ```ts
168
+ import { createMultilangHelpers } from '@roxxel/payload-multilang'
169
+ import { getPayload } from 'payload'
170
+ import config from '@payload-config'
171
+
172
+ export const multilang = createMultilangHelpers({
173
+ getPayload: () => getPayload({ config }),
174
+ })
175
+ ```
176
+
141
177
  ## Documentation
142
178
 
143
179
  - [Configuration](./docs/configuration.md)
@@ -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": "Language",
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: "All languages"
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=\"Language\"\n disabled={isTransitioning}\n onChange={(event) => handleLanguageChange(event.target.value)}\n value={currentLanguage}\n >\n <option value=\"\">All languages</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","usePathname","useRouter","useSearchParams","useMemo","getCollectionFieldNames","getConfiguredLanguagesFromConfig","LanguageListToolbar","collectionSlug","config","pathname","router","searchParams","isTransitioning","startRouteTransition","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,QAAQ,iBAAgB;AAC9D,SAASC,WAAW,EAAEC,SAAS,EAAEC,eAAe,QAAQ,qBAAoB;AAC5E,SAASC,OAAO,QAAQ,QAAO;AAE/B,OAAO,sBAAqB;AAC5B,SAASC,uBAAuB,EAAEC,gCAAgC,QAAQ,cAAa;AAMvF,OAAO,MAAMC,sBAAsB,CAAC,EAAEC,cAAc,EAAS;IAC3D,MAAM,EAAEC,MAAM,EAAE,GAAGV;IACnB,MAAMW,WAAWT;IACjB,MAAMU,SAAST;IACf,MAAMU,eAAeT;IACrB,MAAM,EAAEU,eAAe,EAAEC,oBAAoB,EAAE,GAAGd;IAClD,MAAMe,YAAYT,iCAAiCG;IACnD,MAAMO,aAAaZ,QACjB,IAAMC,wBAAwB;YAAEG;YAAgBC;QAAO,IACvD;QAACD;QAAgBC;KAAO;IAE1B,MAAMQ,gBAAgB,CAAC,MAAM,EAAED,WAAWE,QAAQ,CAAC,SAAS,CAAC;IAC7D,MAAMC,kBAAkBP,aAAaQ,GAAG,CAACH,kBAAkB;IAE3D,IAAI,CAACF,UAAUM,MAAM,EAAE;QACrB,OAAO;IACT;IAEA,MAAMC,uBAAuB,CAACJ;QAC5B,MAAMK,aAAa,IAAIC,gBAAgBZ,aAAaa,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,GAAGlB,SAAS,CAAC,EAAEkB,OAAO,GAAGlB;QAE9CI,qBAAqB;YACnBH,OAAOmB,IAAI,CAACD;QACd;IACF;IAEA,qBACE,KAACE;QAAIC,WAAU;QAA4BC,eAAY;kBACrD,cAAA,KAACC;YAAMF,WAAU;sBACf,cAAA,MAACG;gBACCC,cAAW;gBACXC,UAAUxB;gBACVyB,UAAU,CAACC,QAAUjB,qBAAqBiB,MAAMC,MAAM,CAACC,KAAK;gBAC5DA,OAAOtB;;kCAEP,KAACuB;wBAAOD,OAAM;kCAAG;;oBAChB1B,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
+ {"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 { collectionSlug, id } = useDocumentInfo();
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('Save the document before creating translations.');
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 || 'Translation could not be created.');
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: "Language"
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: "Language"
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: "Unassigned"
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: "Translations"
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: "Current"
240
+ children: t('payloadMultilang:current')
244
241
  }) : isUnavailableForCreate ? /*#__PURE__*/ _jsx("span", {
245
242
  className: "payload-multilang-translation-row__current",
246
- children: "Localized"
243
+ children: t('payloadMultilang:localized')
247
244
  }) : translationID ? /*#__PURE__*/ _jsx("button", {
248
- "aria-label": `Edit ${language.name} translation`,
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": `Create ${language.name} translation`,
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: "Save before adding translations."
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('Choose a target language.');
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 || 'Translation could not be created.');
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('Target ID and language are required.');
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 || 'Translation could not be connected.');
75
+ toast.error(result?.message || t('payloadMultilang:translationCouldNotBeConnected'));
75
76
  return;
76
77
  }
77
- toast.success('Translation connected.');
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('Translation could not be disconnected.');
97
+ toast.error(t('payloadMultilang:translationCouldNotBeDisconnected'));
97
98
  return;
98
99
  }
99
- toast.success('Translation disconnected.');
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: "Translation actions"
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: "Choose language"
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: "Create translation"
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: "Existing document ID",
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: "Connect existing"
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: "Disconnect this document"
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('Choose a target language.')\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 || 'Translation could not be created.')\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('Target ID and language are required.')\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 || 'Translation could not be connected.')\n return\n }\n\n toast.success('Translation connected.')\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('Translation could not be disconnected.')\n return\n }\n\n toast.success('Translation disconnected.')\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>Translation actions</h2>\n <div className=\"payload-multilang-inline-form\">\n <select\n onChange={(event) => setTargetLanguage(event.target.value)}\n value={targetLanguage}\n >\n <option value=\"\">Choose language</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 Create translation\n </Button>\n </div>\n\n <div className=\"payload-multilang-inline-form\">\n <input\n onChange={(event) => setTargetID(event.target.value)}\n placeholder=\"Existing document ID\"\n value={targetID}\n />\n <Button disabled={isBusy || !targetID || !targetLanguage} onClick={connectTranslation} type=\"button\">\n Connect existing\n </Button>\n </div>\n\n <Button buttonStyle=\"secondary\" disabled={isBusy} onClick={disconnectTranslation} type=\"button\">\n Disconnect this document\n </Button>\n </section>\n )\n}\n"],"names":["Button","toast","useConfig","useRouteTransition","useRouter","formatAdminURL","useState","TranslationActionsClient","collectionSlug","docID","languages","state","config","router","startRouteTransition","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","placeholder","buttonStyle"],"mappings":"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"}
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 ? `Unassigned; stored language "${storedLanguage}" is not configured` : 'Unassigned',
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,