@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.
- package/LICENSE.md +7 -0
- package/README.md +50 -14
- package/dist/components/LanguageListToolbar.js +4 -3
- package/dist/components/LanguageListToolbar.js.map +1 -1
- package/dist/components/LanguageMetabox.js +18 -17
- package/dist/components/LanguageMetabox.js.map +1 -1
- package/dist/components/TranslationActionsClient.js +16 -14
- package/dist/components/TranslationActionsClient.js.map +1 -1
- package/dist/components/TranslationColumnCell.js +4 -1
- package/dist/components/TranslationColumnCell.js.map +1 -1
- package/dist/components/TranslationColumnCellClient.js +16 -7
- package/dist/components/TranslationColumnCellClient.js.map +1 -1
- package/dist/components/TranslationsTab.js +9 -8
- package/dist/components/TranslationsTab.js.map +1 -1
- package/dist/constants.d.ts +4 -1
- package/dist/constants.js +4 -1
- package/dist/constants.js.map +1 -1
- package/dist/endpoints/translations.js +4 -6
- package/dist/endpoints/translations.js.map +1 -1
- package/dist/hooks/translatedCollection.d.ts +2 -1
- package/dist/hooks/translatedCollection.js +122 -15
- package/dist/hooks/translatedCollection.js.map +1 -1
- package/dist/hooks/translatedGlobal.js +5 -1
- package/dist/hooks/translatedGlobal.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +27 -3
- package/dist/index.js.map +1 -1
- package/dist/lib/config.js +2 -10
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/data.d.ts +72 -35
- package/dist/lib/data.js +118 -60
- package/dist/lib/data.js.map +1 -1
- package/dist/translations.d.ts +72 -0
- package/dist/translations.js +72 -0
- package/dist/translations.js.map +1 -0
- package/dist/types.d.ts +0 -19
- package/dist/types.js.map +1 -1
- package/docs/configuration.md +75 -10
- package/docs/helpers.md +95 -121
- package/docs/usage.md +115 -120
- package/package.json +1 -1
- package/dist/payload-config.d.js +0 -2
- package/dist/payload-config.d.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/translations.ts"],"sourcesContent":["export const payloadMultilangTranslations = {\n en: {\n payloadMultilang: {\n allLanguages: 'All languages',\n chooseLanguage: 'Choose language',\n chooseTargetLanguage: 'Choose a target language.',\n connectExisting: 'Connect existing',\n createOrConnectDocuments: 'Create or connect separate localized documents.',\n createTranslation: 'Create translation',\n createTranslationFor: 'Create {{language}} translation',\n current: 'Current',\n disconnectDocument: 'Disconnect this document',\n documentID: 'Document ID',\n editTranslationFor: 'Edit {{language}} translation',\n existingDocumentID: 'Existing document ID',\n language: 'Language',\n linkedDocuments: 'Linked documents',\n localized: 'Localized',\n localizedContent: 'Localized content',\n missing: 'Missing',\n saveBeforeAddingTranslations: 'Save before adding translations.',\n saveBeforeCreatingTranslations: 'Save the document before creating translations.',\n saveBeforeManagingTranslations: 'Save the document before managing translations.',\n targetIDAndLanguageRequired: 'Target ID and language are required.',\n translationActions: 'Translation actions',\n translationConnected: 'Translation connected.',\n translationCouldNotBeConnected: 'Translation could not be connected.',\n translationCouldNotBeCreated: 'Translation could not be created.',\n translationCouldNotBeDisconnected: 'Translation could not be disconnected.',\n translationDisconnected: 'Translation disconnected.',\n translations: 'Translations',\n unassigned: 'Unassigned',\n unassignedStoredLanguageNotConfigured:\n 'Unassigned; stored language \"{{language}}\" is not configured',\n },\n },\n uk: {\n payloadMultilang: {\n allLanguages: 'Усі мови',\n chooseLanguage: 'Оберіть мову',\n chooseTargetLanguage: 'Оберіть цільову мову.',\n connectExisting: 'Підключити наявний',\n createOrConnectDocuments: 'Створюйте або підключайте окремі локалізовані документи.',\n createTranslation: 'Створити переклад',\n createTranslationFor: 'Створити переклад: {{language}}',\n current: 'Поточний',\n disconnectDocument: 'Від’єднати цей документ',\n documentID: 'ID документа',\n editTranslationFor: 'Редагувати переклад: {{language}}',\n existingDocumentID: 'ID наявного документа',\n language: 'Мова',\n linkedDocuments: 'Пов’язані документи',\n localized: 'Локалізовано',\n localizedContent: 'Локалізований вміст',\n missing: 'Відсутній',\n saveBeforeAddingTranslations: 'Збережіть перед додаванням перекладів.',\n saveBeforeCreatingTranslations: 'Збережіть документ перед створенням перекладів.',\n saveBeforeManagingTranslations: 'Збережіть документ перед керуванням перекладами.',\n targetIDAndLanguageRequired: 'Потрібні ID цільового документа та мова.',\n translationActions: 'Дії з перекладами',\n translationConnected: 'Переклад підключено.',\n translationCouldNotBeConnected: 'Не вдалося підключити переклад.',\n translationCouldNotBeCreated: 'Не вдалося створити переклад.',\n translationCouldNotBeDisconnected: 'Не вдалося від’єднати переклад.',\n translationDisconnected: 'Переклад від’єднано.',\n translations: 'Переклади',\n unassigned: 'Не призначено',\n unassignedStoredLanguageNotConfigured:\n 'Не призначено; збережена мова \"{{language}}\" не налаштована',\n },\n },\n} as const\n\nexport type PayloadMultilangTranslations =\n (typeof payloadMultilangTranslations)['en']\n\nexport type PayloadMultilangTranslationKey =\n `payloadMultilang:${keyof PayloadMultilangTranslations['payloadMultilang']}`\n"],"names":["payloadMultilangTranslations","en","payloadMultilang","allLanguages","chooseLanguage","chooseTargetLanguage","connectExisting","createOrConnectDocuments","createTranslation","createTranslationFor","current","disconnectDocument","documentID","editTranslationFor","existingDocumentID","language","linkedDocuments","localized","localizedContent","missing","saveBeforeAddingTranslations","saveBeforeCreatingTranslations","saveBeforeManagingTranslations","targetIDAndLanguageRequired","translationActions","translationConnected","translationCouldNotBeConnected","translationCouldNotBeCreated","translationCouldNotBeDisconnected","translationDisconnected","translations","unassigned","unassignedStoredLanguageNotConfigured","uk"],"mappings":"AAAA,OAAO,MAAMA,+BAA+B;IAC1CC,IAAI;QACFC,kBAAkB;YAChBC,cAAc;YACdC,gBAAgB;YAChBC,sBAAsB;YACtBC,iBAAiB;YACjBC,0BAA0B;YAC1BC,mBAAmB;YACnBC,sBAAsB;YACtBC,SAAS;YACTC,oBAAoB;YACpBC,YAAY;YACZC,oBAAoB;YACpBC,oBAAoB;YACpBC,UAAU;YACVC,iBAAiB;YACjBC,WAAW;YACXC,kBAAkB;YAClBC,SAAS;YACTC,8BAA8B;YAC9BC,gCAAgC;YAChCC,gCAAgC;YAChCC,6BAA6B;YAC7BC,oBAAoB;YACpBC,sBAAsB;YACtBC,gCAAgC;YAChCC,8BAA8B;YAC9BC,mCAAmC;YACnCC,yBAAyB;YACzBC,cAAc;YACdC,YAAY;YACZC,uCACE;QACJ;IACF;IACAC,IAAI;QACF/B,kBAAkB;YAChBC,cAAc;YACdC,gBAAgB;YAChBC,sBAAsB;YACtBC,iBAAiB;YACjBC,0BAA0B;YAC1BC,mBAAmB;YACnBC,sBAAsB;YACtBC,SAAS;YACTC,oBAAoB;YACpBC,YAAY;YACZC,oBAAoB;YACpBC,oBAAoB;YACpBC,UAAU;YACVC,iBAAiB;YACjBC,WAAW;YACXC,kBAAkB;YAClBC,SAAS;YACTC,8BAA8B;YAC9BC,gCAAgC;YAChCC,gCAAgC;YAChCC,6BAA6B;YAC7BC,oBAAoB;YACpBC,sBAAsB;YACtBC,gCAAgC;YAChCC,8BAA8B;YAC9BC,mCAAmC;YACnCC,yBAAyB;YACzBC,cAAc;YACdC,YAAY;YACZC,uCACE;QACJ;IACF;AACF,EAAU"}
|
package/dist/types.d.ts
CHANGED
|
@@ -17,22 +17,10 @@ export type MultilangLanguage = {
|
|
|
17
17
|
order?: number;
|
|
18
18
|
};
|
|
19
19
|
export type MultilangCollectionOptions = {
|
|
20
|
-
/**
|
|
21
|
-
* Set to false to create empty translation documents by default.
|
|
22
|
-
*/
|
|
23
|
-
duplicate?: boolean;
|
|
24
|
-
/**
|
|
25
|
-
* Additional top-level document field names that should not be copied when creating a translation.
|
|
26
|
-
*/
|
|
27
|
-
duplicateExcludeFields?: string[];
|
|
28
20
|
/**
|
|
29
21
|
* Override hidden metadata field names for this collection.
|
|
30
22
|
*/
|
|
31
23
|
fields?: Partial<MultilangFieldNames>;
|
|
32
|
-
/**
|
|
33
|
-
* Top-level document field names that should share one value across every language in a translation group.
|
|
34
|
-
*/
|
|
35
|
-
synchronizedFields?: string[];
|
|
36
24
|
};
|
|
37
25
|
export type MultilangGlobalOptions = {
|
|
38
26
|
/**
|
|
@@ -49,10 +37,6 @@ export type PayloadMultilangConfig = {
|
|
|
49
37
|
* Disable runtime UI/endpoints/hooks while keeping schema fields in place.
|
|
50
38
|
*/
|
|
51
39
|
disabled?: boolean;
|
|
52
|
-
/**
|
|
53
|
-
* Global duplicate exclusions applied to all enabled collections.
|
|
54
|
-
*/
|
|
55
|
-
duplicateExcludeFields?: string[];
|
|
56
40
|
/**
|
|
57
41
|
* Global hidden metadata field name overrides.
|
|
58
42
|
*/
|
|
@@ -69,12 +53,9 @@ export type PayloadMultilangConfig = {
|
|
|
69
53
|
};
|
|
70
54
|
export type ResolvedMultilangCollection = {
|
|
71
55
|
defaultLanguage: MultilangLanguage;
|
|
72
|
-
duplicate: boolean;
|
|
73
|
-
duplicateExcludeFields: string[];
|
|
74
56
|
fieldNames: MultilangFieldNames;
|
|
75
57
|
languages: MultilangLanguage[];
|
|
76
58
|
slug: string;
|
|
77
|
-
synchronizedFields: string[];
|
|
78
59
|
};
|
|
79
60
|
export type ResolvedMultilangGlobal = {
|
|
80
61
|
defaultLanguage: MultilangLanguage;
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["import type { CollectionSlug, GlobalSlug, Where } from 'payload'\n\nexport type MultilangDirection = 'ltr' | 'rtl'\n\nexport type MultilangFieldNames = {\n group: string\n language: string\n meta: string\n}\n\nexport type MultilangLanguage = {\n active?: boolean\n code: string\n direction?: MultilangDirection\n flagLabel?: string\n id?: number | string\n isDefault?: boolean\n locale?: string\n name: string\n order?: number\n}\n\nexport type MultilangCollectionOptions = {\n /**\n *
|
|
1
|
+
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["import type { CollectionSlug, GlobalSlug, Where } from 'payload'\n\nexport type MultilangDirection = 'ltr' | 'rtl'\n\nexport type MultilangFieldNames = {\n group: string\n language: string\n meta: string\n}\n\nexport type MultilangLanguage = {\n active?: boolean\n code: string\n direction?: MultilangDirection\n flagLabel?: string\n id?: number | string\n isDefault?: boolean\n locale?: string\n name: string\n order?: number\n}\n\nexport type MultilangCollectionOptions = {\n /**\n * Override hidden metadata field names for this collection.\n */\n fields?: Partial<MultilangFieldNames>\n}\n\nexport type MultilangGlobalOptions = {\n /**\n * Override the top-level tabs field label used to group localized global fields.\n */\n label?: string\n}\n\nexport type PayloadMultilangConfig = {\n /**\n * Payload collections that should use Polylang-style document translations.\n */\n collections?: Partial<Record<CollectionSlug, MultilangCollectionOptions | true>>\n /**\n * Disable runtime UI/endpoints/hooks while keeping schema fields in place.\n */\n disabled?: boolean\n /**\n * Global hidden metadata field name overrides.\n */\n fieldNames?: Partial<MultilangFieldNames>\n /**\n * Payload globals that should store language-specific values in one singleton document.\n */\n globals?: Partial<Record<GlobalSlug, MultilangGlobalOptions | true>>\n /**\n * Languages available to translated collections. Codes are normalized to\n * lowercase during plugin setup.\n */\n languages: MultilangLanguage[]\n}\n\nexport type ResolvedMultilangCollection = {\n defaultLanguage: MultilangLanguage\n fieldNames: MultilangFieldNames\n languages: MultilangLanguage[]\n slug: string\n}\n\nexport type ResolvedMultilangGlobal = {\n defaultLanguage: MultilangLanguage\n label: string\n languages: MultilangLanguage[]\n slug: string\n}\n\nexport type TranslationMap<TDoc = Record<string, unknown>> = Record<string, TDoc>\n\nexport type TranslationState<TDoc = Record<string, unknown>> = {\n group?: string\n language?: string\n source?: TDoc\n translations: TranslationMap<TDoc>\n}\n\nexport type WithLanguageArgs = {\n fieldName?: string\n language: string\n where?: Where\n}\n"],"names":[],"mappings":"AAmFA,WAIC"}
|
package/docs/configuration.md
CHANGED
|
@@ -32,6 +32,8 @@ export default buildConfig({
|
|
|
32
32
|
})
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
+
Payload built-in localization must stay disabled. This plugin models translations as separate documents linked by metadata fields, so `localized: true` fields are not the intended model. If `config.localization` is enabled, `payloadMultilang()` throws during config setup.
|
|
36
|
+
|
|
35
37
|
## Plugin Options
|
|
36
38
|
|
|
37
39
|
| Option | Type | Description |
|
|
@@ -40,9 +42,47 @@ export default buildConfig({
|
|
|
40
42
|
| `collections` | `Record<string, true \| MultilangCollectionOptions>` | Collection slugs to localize. |
|
|
41
43
|
| `globals` | `Record<string, true \| MultilangGlobalOptions>` | Global slugs to localize. |
|
|
42
44
|
| `fieldNames` | `Partial<MultilangFieldNames>` | Optional custom field names used by localized collections. |
|
|
43
|
-
| `duplicateExcludeFields` | `string[]` | Extra top-level fields to skip when a new translation duplicates source document data. |
|
|
44
45
|
| `disabled` | `boolean` | Returns the Payload config unchanged when true. Useful for temporary opt-out in specific environments. |
|
|
45
46
|
|
|
47
|
+
## Content Model
|
|
48
|
+
|
|
49
|
+
Translated collection entries are independent Payload documents. The plugin adds hidden metadata fields:
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
{
|
|
53
|
+
language: '_multilangLanguage',
|
|
54
|
+
group: '_multilangGroup',
|
|
55
|
+
meta: '_multilangMeta',
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Do not mark content fields as `localized: true` for this plugin model. Put translated text directly on each language document instead.
|
|
60
|
+
|
|
61
|
+
## Admin UI Translations
|
|
62
|
+
|
|
63
|
+
The plugin registers its own admin UI translations for English (`en`) and Ukrainian (`uk`) through Payload `i18n.translations`.
|
|
64
|
+
|
|
65
|
+
Apps can override any plugin string by setting the same translation keys after installing the plugin:
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
export default buildConfig({
|
|
69
|
+
i18n: {
|
|
70
|
+
translations: {
|
|
71
|
+
uk: {
|
|
72
|
+
payloadMultilang: {
|
|
73
|
+
translations: 'Переклади',
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
plugins: [
|
|
79
|
+
payloadMultilang({
|
|
80
|
+
languages,
|
|
81
|
+
}),
|
|
82
|
+
],
|
|
83
|
+
})
|
|
84
|
+
```
|
|
85
|
+
|
|
46
86
|
## Languages
|
|
47
87
|
|
|
48
88
|
```ts
|
|
@@ -101,11 +141,7 @@ Use collection options when you need custom translation behavior.
|
|
|
101
141
|
```ts
|
|
102
142
|
payloadMultilang({
|
|
103
143
|
collections: {
|
|
104
|
-
posts:
|
|
105
|
-
duplicate: true,
|
|
106
|
-
duplicateExcludeFields: ['legacyId'],
|
|
107
|
-
synchronizedFields: ['featuredImage', 'author'],
|
|
108
|
-
},
|
|
144
|
+
posts: true,
|
|
109
145
|
},
|
|
110
146
|
languages,
|
|
111
147
|
})
|
|
@@ -113,10 +149,24 @@ payloadMultilang({
|
|
|
113
149
|
|
|
114
150
|
| Option | Type | Description |
|
|
115
151
|
| ------------------------ | ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
116
|
-
| `duplicate` | `boolean` | Defaults to `true`. When creating a translation, copy source document fields into the new document. Set to `false` to create empty translation documents by default. |
|
|
117
|
-
| `duplicateExcludeFields` | `string[]` | Additional top-level fields to skip during duplication for this collection. |
|
|
118
152
|
| `fields` | `Partial<MultilangFieldNames>` | Override metadata field names for this collection. |
|
|
119
|
-
|
|
153
|
+
|
|
154
|
+
Mark fields that should stay shared across translations directly in the field config:
|
|
155
|
+
|
|
156
|
+
```ts
|
|
157
|
+
{
|
|
158
|
+
name: 'featuredImage',
|
|
159
|
+
type: 'upload',
|
|
160
|
+
relationTo: 'media',
|
|
161
|
+
custom: {
|
|
162
|
+
multilang: {
|
|
163
|
+
synchronize: true,
|
|
164
|
+
},
|
|
165
|
+
},
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
For repeatable fields with child fields, such as `array` and `blocks`, synchronization only applies to the outer shell. Item IDs, order, block types, and block names follow the source document, while each translation keeps its own nested field values.
|
|
120
170
|
|
|
121
171
|
## Globals
|
|
122
172
|
|
|
@@ -144,7 +194,7 @@ payloadMultilang({
|
|
|
144
194
|
})
|
|
145
195
|
```
|
|
146
196
|
|
|
147
|
-
Read and update localized global values with `
|
|
197
|
+
Read and update localized global values with `findGlobalByLanguageWithPayload`, `updateGlobalByLanguageWithPayload`, or helpers from `createMultilangHelpers()`.
|
|
148
198
|
|
|
149
199
|
## Custom Field Names
|
|
150
200
|
|
|
@@ -190,3 +240,18 @@ payloadMultilang({
|
|
|
190
240
|
```
|
|
191
241
|
|
|
192
242
|
When using custom field names, pass the same names to helpers that accept `fieldNames` or `fieldName`.
|
|
243
|
+
|
|
244
|
+
## Slug Uniqueness
|
|
245
|
+
|
|
246
|
+
Because translations are separate documents, decide whether slugs are unique globally or per language.
|
|
247
|
+
|
|
248
|
+
If every translated document has a different slug, a normal `unique: true` slug field works. If translations may share the same slug across languages, do not use global `unique: true`; enforce uniqueness with a compound database index or a custom validation rule scoped to:
|
|
249
|
+
|
|
250
|
+
```ts
|
|
251
|
+
{
|
|
252
|
+
_multilangLanguage: language,
|
|
253
|
+
slug,
|
|
254
|
+
}
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
Use `localizedSlugQuery()` for common language + slug lookups in frontend routes.
|
package/docs/helpers.md
CHANGED
|
@@ -2,33 +2,52 @@
|
|
|
2
2
|
|
|
3
3
|
Import helpers from `@roxxel/payload-multilang`.
|
|
4
4
|
|
|
5
|
+
## Request-Scoped Helpers
|
|
6
|
+
|
|
7
|
+
Use `WithPayload` helpers in endpoints, hooks, route handlers, and code running on behalf of a user.
|
|
8
|
+
|
|
5
9
|
```ts
|
|
6
10
|
import {
|
|
7
|
-
findGlobalByLanguage,
|
|
8
11
|
findGlobalByLanguageWithPayload,
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
updateGlobalByLanguage,
|
|
12
|
+
getDocumentTranslationWithPayload,
|
|
13
|
+
getDocumentTranslationsWithPayload,
|
|
14
|
+
getGroupTranslationsWithPayload,
|
|
13
15
|
updateGlobalByLanguageWithPayload,
|
|
14
|
-
withLanguage,
|
|
15
16
|
} from '@roxxel/payload-multilang'
|
|
17
|
+
|
|
18
|
+
const state = await getDocumentTranslationsWithPayload({
|
|
19
|
+
collection: 'posts',
|
|
20
|
+
id: post.id,
|
|
21
|
+
payload: req.payload,
|
|
22
|
+
req,
|
|
23
|
+
overrideAccess: false,
|
|
24
|
+
})
|
|
16
25
|
```
|
|
17
26
|
|
|
18
|
-
|
|
27
|
+
`overrideAccess` defaults to `true`, matching Payload Local API defaults. Set it to `false` and pass `req` when enforcing request user access.
|
|
28
|
+
|
|
29
|
+
## `createMultilangHelpers`
|
|
19
30
|
|
|
20
|
-
|
|
31
|
+
Use a tiny app-owned module for convenience helpers.
|
|
21
32
|
|
|
22
33
|
```ts
|
|
23
|
-
|
|
34
|
+
import { createMultilangHelpers } from '@roxxel/payload-multilang'
|
|
35
|
+
import { getPayload } from 'payload'
|
|
36
|
+
import config from '@payload-config'
|
|
37
|
+
|
|
38
|
+
export const multilang = createMultilangHelpers({
|
|
39
|
+
getPayload: () => getPayload({ config }),
|
|
40
|
+
})
|
|
24
41
|
```
|
|
25
42
|
|
|
26
|
-
|
|
43
|
+
The factory returns:
|
|
27
44
|
|
|
28
45
|
```ts
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
46
|
+
multilang.getLanguages()
|
|
47
|
+
multilang.getDocumentTranslations(args)
|
|
48
|
+
multilang.getDocumentTranslation(args)
|
|
49
|
+
multilang.findGlobalByLanguage(args)
|
|
50
|
+
multilang.updateGlobalByLanguage(args)
|
|
32
51
|
```
|
|
33
52
|
|
|
34
53
|
## `withLanguage`
|
|
@@ -36,6 +55,8 @@ const languages = await getLanguages({
|
|
|
36
55
|
Adds a language constraint to a Payload `where` query.
|
|
37
56
|
|
|
38
57
|
```ts
|
|
58
|
+
import { withLanguage } from '@roxxel/payload-multilang'
|
|
59
|
+
|
|
39
60
|
const where = withLanguage({
|
|
40
61
|
language: 'uk',
|
|
41
62
|
where: {
|
|
@@ -65,37 +86,31 @@ Result:
|
|
|
65
86
|
}
|
|
66
87
|
```
|
|
67
88
|
|
|
68
|
-
Signature:
|
|
69
|
-
|
|
70
|
-
```ts
|
|
71
|
-
withLanguage(args: {
|
|
72
|
-
fieldName?: string
|
|
73
|
-
language: string
|
|
74
|
-
where?: Where
|
|
75
|
-
}): Where
|
|
76
|
-
```
|
|
77
|
-
|
|
78
89
|
Use `fieldName` if you configured a custom collection language field.
|
|
79
90
|
|
|
80
|
-
##
|
|
91
|
+
## Document Helpers
|
|
81
92
|
|
|
82
|
-
|
|
93
|
+
`getDocumentTranslationsWithPayload` returns the source document and all linked translations for a localized collection document.
|
|
83
94
|
|
|
84
95
|
```ts
|
|
85
|
-
const state = await
|
|
96
|
+
const state = await getDocumentTranslationsWithPayload<Post>({
|
|
86
97
|
collection: 'posts',
|
|
87
98
|
id: post.id,
|
|
99
|
+
payload: req.payload,
|
|
100
|
+
req,
|
|
101
|
+
overrideAccess: false,
|
|
88
102
|
})
|
|
89
103
|
```
|
|
90
104
|
|
|
91
|
-
|
|
105
|
+
`getDocumentTranslationWithPayload` returns one target-language document.
|
|
92
106
|
|
|
93
107
|
```ts
|
|
94
|
-
|
|
95
|
-
collection:
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
108
|
+
const ukrainianPost = await getDocumentTranslationWithPayload<Post>({
|
|
109
|
+
collection: 'posts',
|
|
110
|
+
id: post.id,
|
|
111
|
+
language: 'uk',
|
|
112
|
+
payload: req.payload,
|
|
113
|
+
})
|
|
99
114
|
```
|
|
100
115
|
|
|
101
116
|
Return shape:
|
|
@@ -109,123 +124,82 @@ type TranslationState<TDoc = Record<string, unknown>> = {
|
|
|
109
124
|
}
|
|
110
125
|
```
|
|
111
126
|
|
|
112
|
-
##
|
|
127
|
+
## Global Helpers
|
|
113
128
|
|
|
114
|
-
|
|
129
|
+
Localized globals store one singleton document with one top-level tab per language. These helpers read or update one tab and return flat data for that language.
|
|
115
130
|
|
|
116
131
|
```ts
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
id: post.id,
|
|
132
|
+
const settings = await findGlobalByLanguageWithPayload<SiteSettings>({
|
|
133
|
+
slug: 'site-settings',
|
|
120
134
|
language: 'uk',
|
|
135
|
+
payload: req.payload,
|
|
136
|
+
req,
|
|
137
|
+
overrideAccess: false,
|
|
121
138
|
})
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
Signature:
|
|
125
|
-
|
|
126
|
-
```ts
|
|
127
|
-
getDocumentTranslation<TDoc>(args: {
|
|
128
|
-
collection: CollectionSlug
|
|
129
|
-
fieldNames?: MultilangFieldNames
|
|
130
|
-
id: number | string
|
|
131
|
-
language: string
|
|
132
|
-
}): Promise<TDoc | undefined>
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
## `findGlobalByLanguage`
|
|
136
|
-
|
|
137
|
-
Reads one language from a localized global and returns flat data for that language.
|
|
138
139
|
|
|
139
|
-
|
|
140
|
-
const settings = await findGlobalByLanguage<SiteSettings>({
|
|
140
|
+
await updateGlobalByLanguageWithPayload<SiteSettings>({
|
|
141
141
|
slug: 'site-settings',
|
|
142
142
|
language: 'uk',
|
|
143
|
+
payload: req.payload,
|
|
144
|
+
data: {
|
|
145
|
+
title: 'Updated title',
|
|
146
|
+
},
|
|
143
147
|
})
|
|
144
148
|
```
|
|
145
149
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
```ts
|
|
149
|
-
findGlobalByLanguage<TDoc>(args: {
|
|
150
|
-
depth?: number
|
|
151
|
-
language: string
|
|
152
|
-
slug: GlobalSlug
|
|
153
|
-
}): Promise<TDoc>
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
## `updateGlobalByLanguage`
|
|
150
|
+
## Constants
|
|
157
151
|
|
|
158
|
-
|
|
152
|
+
Default metadata field names are exported so apps do not need to hardcode them.
|
|
159
153
|
|
|
160
154
|
```ts
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
})
|
|
155
|
+
import {
|
|
156
|
+
DEFAULT_FIELD_NAMES,
|
|
157
|
+
MULTILANG_GROUP_FIELD,
|
|
158
|
+
MULTILANG_LANGUAGE_FIELD,
|
|
159
|
+
MULTILANG_META_FIELD,
|
|
160
|
+
} from '@roxxel/payload-multilang'
|
|
168
161
|
```
|
|
169
162
|
|
|
170
|
-
|
|
163
|
+
Values:
|
|
171
164
|
|
|
172
165
|
```ts
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
}): Promise<TDoc>
|
|
166
|
+
{
|
|
167
|
+
language: '_multilangLanguage',
|
|
168
|
+
group: '_multilangGroup',
|
|
169
|
+
meta: '_multilangMeta',
|
|
170
|
+
}
|
|
179
171
|
```
|
|
180
172
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
## Global Helpers With Payload
|
|
173
|
+
## Preview Language Helper
|
|
184
174
|
|
|
185
|
-
Use
|
|
175
|
+
Use `getMultilangDocumentLanguage` in admin preview or livePreview URL builders. It checks unsaved form data first, then the persisted document.
|
|
186
176
|
|
|
187
177
|
```ts
|
|
188
|
-
|
|
189
|
-
slug: 'site-settings',
|
|
190
|
-
language: 'uk',
|
|
191
|
-
overrideAccess: false,
|
|
192
|
-
payload: req.payload,
|
|
193
|
-
req,
|
|
194
|
-
})
|
|
178
|
+
import { getMultilangDocumentLanguage } from '@roxxel/payload-multilang'
|
|
195
179
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
title: 'Updated title',
|
|
201
|
-
},
|
|
202
|
-
overrideAccess: false,
|
|
203
|
-
payload: req.payload,
|
|
204
|
-
req,
|
|
180
|
+
const language = getMultilangDocumentLanguage({
|
|
181
|
+
data,
|
|
182
|
+
doc,
|
|
183
|
+
fallback: 'en',
|
|
205
184
|
})
|
|
206
185
|
```
|
|
207
186
|
|
|
208
|
-
|
|
187
|
+
## Localized Slug Query
|
|
188
|
+
|
|
189
|
+
`localizedSlugQuery` builds the common Local API query for language + slug + status.
|
|
209
190
|
|
|
210
191
|
```ts
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
depth?: number
|
|
223
|
-
language: string
|
|
224
|
-
overrideAccess?: boolean
|
|
225
|
-
payload: Payload
|
|
226
|
-
req?: PayloadRequest
|
|
227
|
-
slug: GlobalSlug
|
|
228
|
-
}): Promise<TDoc>
|
|
192
|
+
import { localizedSlugQuery } from '@roxxel/payload-multilang'
|
|
193
|
+
|
|
194
|
+
const { docs } = await payload.find({
|
|
195
|
+
collection: 'posts',
|
|
196
|
+
limit: 1,
|
|
197
|
+
...localizedSlugQuery({
|
|
198
|
+
slug,
|
|
199
|
+
language: 'uk',
|
|
200
|
+
status: 'published',
|
|
201
|
+
}),
|
|
202
|
+
})
|
|
229
203
|
```
|
|
230
204
|
|
|
231
|
-
`
|
|
205
|
+
Use `status: 'draft'` to include `draft: true` and `_status = draft`, or `status: 'any'` to omit `_status`.
|