@nitrogenbuilder/connector-payload 1.1.1 → 1.2.0
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/dist/collections/NitrogenTemplates.js +8 -0
- package/dist/endpoints/all.js +3 -0
- package/dist/endpoints/batch.js +9 -0
- package/dist/endpoints/collection-endpoints.js +119 -3
- package/dist/endpoints/helpers.js +2 -1
- package/dist/endpoints/menu.js +2 -0
- package/dist/endpoints/sitemap.js +47 -7
- package/dist/endpoints/templates.js +116 -0
- package/dist/endpoints/translation-status.d.ts +11 -0
- package/dist/endpoints/translation-status.js +105 -0
- package/dist/frontend/NitrogenPageClient.d.ts +6 -1
- package/dist/frontend/NitrogenPageClient.js +6 -2
- package/dist/frontend/NitrogenWrapper.d.ts +8 -1
- package/dist/frontend/NitrogenWrapper.js +25 -3
- package/dist/index.d.ts +22 -0
- package/dist/index.js +69 -2
- package/dist/inventory/indexing.d.ts +2 -0
- package/dist/inventory/indexing.js +1 -0
- package/dist/localization.d.ts +121 -0
- package/dist/localization.js +563 -0
- package/dist/types.d.ts +3 -0
- package/package.json +1 -1
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Translation status route — lists per-language translation coverage for
|
|
3
|
+
* every Nitrogen-enabled document and template, for the editor's translation
|
|
4
|
+
* dashboard.
|
|
5
|
+
*
|
|
6
|
+
* The status is computed and stored (in `nitrogenTranslationStatus`) by the
|
|
7
|
+
* save handlers; this route reads the stored value and only computes on the
|
|
8
|
+
* fly for docs that have never been saved since localization was enabled.
|
|
9
|
+
*/
|
|
10
|
+
import { getNitrogenSettings, requireAuth } from './helpers.js';
|
|
11
|
+
import { findAllDocs } from '../inventory/indexing.js';
|
|
12
|
+
import { computeDocTranslationStatus, getLocalizationSettings, getPayloadLocalization, loadTranslatablePropDefs, } from '../localization.js';
|
|
13
|
+
function isStoredStatus(value) {
|
|
14
|
+
return !!value && typeof value === 'object' && !Array.isArray(value);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Docs fetched at locale 'all' carry localized fields as locale-keyed
|
|
18
|
+
* objects — read the default language's title in that case.
|
|
19
|
+
*/
|
|
20
|
+
function docTitle(doc, defaultLanguage) {
|
|
21
|
+
const title = doc.title;
|
|
22
|
+
if (typeof title === 'string')
|
|
23
|
+
return title;
|
|
24
|
+
if (title && typeof title === 'object' && !Array.isArray(title)) {
|
|
25
|
+
const record = title;
|
|
26
|
+
const value = record[defaultLanguage];
|
|
27
|
+
if (typeof value === 'string')
|
|
28
|
+
return value;
|
|
29
|
+
// No default-language title — fall back to the first stored one, matching
|
|
30
|
+
// the renderer's language-resolution fallback chain.
|
|
31
|
+
for (const candidate of Object.values(record)) {
|
|
32
|
+
if (typeof candidate === 'string' && candidate)
|
|
33
|
+
return candidate;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return '';
|
|
37
|
+
}
|
|
38
|
+
export function createTranslationStatusEndpoints(collections) {
|
|
39
|
+
return [
|
|
40
|
+
// GET /api/nitrogen/v1/translation-status — TranslationStatusEntry[] across
|
|
41
|
+
// configured collections + nitrogen-templates
|
|
42
|
+
{
|
|
43
|
+
path: '/nitrogen/v1/translation-status',
|
|
44
|
+
method: 'get',
|
|
45
|
+
handler: async (req) => {
|
|
46
|
+
const authError = requireAuth(req);
|
|
47
|
+
if (authError)
|
|
48
|
+
return authError;
|
|
49
|
+
const { payload } = req;
|
|
50
|
+
const settings = await getNitrogenSettings(payload);
|
|
51
|
+
const localization = getLocalizationSettings(settings);
|
|
52
|
+
if (!localization) {
|
|
53
|
+
return Response.json([]);
|
|
54
|
+
}
|
|
55
|
+
// One catalog load shared by every on-the-fly computation.
|
|
56
|
+
const propDefs = await loadTranslatablePropDefs(payload);
|
|
57
|
+
// With Payload-native localization, fetch docs at locale 'all' so
|
|
58
|
+
// field-level coverage can be read without per-doc re-fetches.
|
|
59
|
+
const locale = getPayloadLocalization(payload) ? 'all' : undefined;
|
|
60
|
+
const entries = [];
|
|
61
|
+
const allCollections = Array.from(new Set([...collections, 'nitrogen-templates']));
|
|
62
|
+
for (const collectionSlug of allCollections) {
|
|
63
|
+
let docs;
|
|
64
|
+
try {
|
|
65
|
+
docs = await findAllDocs(payload, collectionSlug, { locale });
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
// One bad collection shouldn't 500 the whole listing — skip it.
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
const type = collectionSlug === 'nitrogen-templates' ? 'template' : 'page';
|
|
72
|
+
for (const doc of docs) {
|
|
73
|
+
let languages = null;
|
|
74
|
+
if (isStoredStatus(doc.nitrogenTranslationStatus)) {
|
|
75
|
+
languages = doc.nitrogenTranslationStatus;
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
try {
|
|
79
|
+
languages = await computeDocTranslationStatus({
|
|
80
|
+
payload,
|
|
81
|
+
collectionSlug,
|
|
82
|
+
docId: doc.id,
|
|
83
|
+
nitrogenData: doc.nitrogenData,
|
|
84
|
+
localization,
|
|
85
|
+
propDefs,
|
|
86
|
+
localeAllDoc: locale ? doc : null,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
languages = null;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
entries.push({
|
|
94
|
+
id: doc.id,
|
|
95
|
+
title: docTitle(doc, localization.defaultLanguage),
|
|
96
|
+
type,
|
|
97
|
+
languages: languages || {},
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return Response.json(entries);
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
];
|
|
105
|
+
}
|
|
@@ -5,6 +5,11 @@ export interface NitrogenPageClientProps {
|
|
|
5
5
|
dynamicData: Record<string, unknown>;
|
|
6
6
|
isBuilder?: boolean;
|
|
7
7
|
collection?: string;
|
|
8
|
+
/**
|
|
9
|
+
* Language to render translatable builder props in (a configured language
|
|
10
|
+
* code). Forwarded to NitrogenRenderer. Omit for the default language.
|
|
11
|
+
*/
|
|
12
|
+
language?: string;
|
|
8
13
|
}
|
|
9
14
|
/**
|
|
10
15
|
* Client component that renders Nitrogen pages using React.
|
|
@@ -12,5 +17,5 @@ export interface NitrogenPageClientProps {
|
|
|
12
17
|
* Uses `useNitrogenData` hook for live preview updates in builder mode,
|
|
13
18
|
* and `NitrogenRenderer` for React-based rendering of the component tree.
|
|
14
19
|
*/
|
|
15
|
-
export declare function NitrogenPageClient({ pageId, pageData, dynamicData: initialDynamicData, isBuilder, collection, }: NitrogenPageClientProps): import("react/jsx-runtime").JSX.Element;
|
|
20
|
+
export declare function NitrogenPageClient({ pageId, pageData, dynamicData: initialDynamicData, isBuilder, collection, language, }: NitrogenPageClientProps): import("react/jsx-runtime").JSX.Element;
|
|
16
21
|
export default NitrogenPageClient;
|
|
@@ -9,7 +9,7 @@ import { Nitrogen } from "@nitrogenbuilder/client-core";
|
|
|
9
9
|
* Uses `useNitrogenData` hook for live preview updates in builder mode,
|
|
10
10
|
* and `NitrogenRenderer` for React-based rendering of the component tree.
|
|
11
11
|
*/
|
|
12
|
-
export function NitrogenPageClient({ pageId, pageData, dynamicData: initialDynamicData, isBuilder = false, collection, }) {
|
|
12
|
+
export function NitrogenPageClient({ pageId, pageData, dynamicData: initialDynamicData, isBuilder = false, collection, language, }) {
|
|
13
13
|
// Use the hook for live preview updates
|
|
14
14
|
const page = useNitrogenData({
|
|
15
15
|
type: "page",
|
|
@@ -50,6 +50,10 @@ export function NitrogenPageClient({ pageId, pageData, dynamicData: initialDynam
|
|
|
50
50
|
}
|
|
51
51
|
};
|
|
52
52
|
}, [isBuilder]);
|
|
53
|
-
|
|
53
|
+
// The `language` prop is being added to NitrogenRenderer in the client-react
|
|
54
|
+
// package; spread it loosely so this compiles against both old and new
|
|
55
|
+
// renderer typings (older renderers simply ignore the extra prop).
|
|
56
|
+
const languageProp = language ? { language } : {};
|
|
57
|
+
return (_jsx("div", { "data-nitrogen-location": "page", "data-page-id": pageId, "data-collection": collection, "data-language": language, children: _jsx(NitrogenRenderer, { page: page?.data ?? [], dynamicData: page?.dynamicData ?? initialDynamicData, requestedData: {}, ...languageProp }) }));
|
|
54
58
|
}
|
|
55
59
|
export default NitrogenPageClient;
|
|
@@ -25,6 +25,13 @@ export interface NitrogenWrapperProps {
|
|
|
25
25
|
* Regular page content to render when not in Nitrogen mode.
|
|
26
26
|
*/
|
|
27
27
|
children: React.ReactNode;
|
|
28
|
+
/**
|
|
29
|
+
* Language to render the page in (a configured locale code, e.g. 'es').
|
|
30
|
+
* Dynamic data is rebuilt from the doc fetched at that locale, and the
|
|
31
|
+
* language is forwarded to the renderer so translatable builder props
|
|
32
|
+
* resolve to it. Omit for the default language.
|
|
33
|
+
*/
|
|
34
|
+
language?: string;
|
|
28
35
|
}
|
|
29
36
|
/**
|
|
30
37
|
* Server component that wraps your page content and automatically handles
|
|
@@ -45,5 +52,5 @@ export interface NitrogenWrapperProps {
|
|
|
45
52
|
* }
|
|
46
53
|
* ```
|
|
47
54
|
*/
|
|
48
|
-
export declare function NitrogenWrapper({ page, searchParams, collection, config, children, }: NitrogenWrapperProps): Promise<import("react/jsx-runtime").JSX.Element>;
|
|
55
|
+
export declare function NitrogenWrapper({ page, searchParams, collection, config, children, language, }: NitrogenWrapperProps): Promise<import("react/jsx-runtime").JSX.Element>;
|
|
49
56
|
export default NitrogenWrapper;
|
|
@@ -2,6 +2,7 @@ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { getPayload } from 'payload';
|
|
3
3
|
import { NitrogenPageClient } from './NitrogenPageClient.js';
|
|
4
4
|
import { buildDynamicData, getNitrogenSettings } from '../endpoints/helpers.js';
|
|
5
|
+
import { resolveLocaleOptions } from '../localization.js';
|
|
5
6
|
/**
|
|
6
7
|
* Server component that wraps your page content and automatically handles
|
|
7
8
|
* Nitrogen builder mode and Nitrogen-rendered pages.
|
|
@@ -21,7 +22,7 @@ import { buildDynamicData, getNitrogenSettings } from '../endpoints/helpers.js';
|
|
|
21
22
|
* }
|
|
22
23
|
* ```
|
|
23
24
|
*/
|
|
24
|
-
export async function NitrogenWrapper({ page, searchParams, collection, config, children, }) {
|
|
25
|
+
export async function NitrogenWrapper({ page, searchParams, collection, config, children, language, }) {
|
|
25
26
|
const isBuilder = searchParams['nitrogen-builder'] !== undefined;
|
|
26
27
|
const hasNitrogenData = Array.isArray(page.nitrogenData) && page.nitrogenData.length > 0;
|
|
27
28
|
// If not in builder mode and no Nitrogen data, render regular content
|
|
@@ -31,7 +32,28 @@ export async function NitrogenWrapper({ page, searchParams, collection, config,
|
|
|
31
32
|
// Fetch Nitrogen settings and build dynamic data
|
|
32
33
|
const payload = await getPayload({ config });
|
|
33
34
|
const settings = await getNitrogenSettings(payload);
|
|
34
|
-
|
|
35
|
-
|
|
35
|
+
// When a language is requested (and Payload localization is configured),
|
|
36
|
+
// re-fetch the doc at that locale so dynamic data carries the translated
|
|
37
|
+
// field values. Falls back to the passed-in page on any failure.
|
|
38
|
+
let sourceDoc = page;
|
|
39
|
+
const localeOptions = resolveLocaleOptions(payload, language);
|
|
40
|
+
if (localeOptions.locale) {
|
|
41
|
+
try {
|
|
42
|
+
const localized = await payload.findByID({
|
|
43
|
+
collection: collection,
|
|
44
|
+
id: page.id,
|
|
45
|
+
depth: 1,
|
|
46
|
+
...localeOptions,
|
|
47
|
+
});
|
|
48
|
+
if (localized) {
|
|
49
|
+
sourceDoc = localized;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
// Locale fetch is best-effort — keep the caller's doc.
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const dynamicData = buildDynamicData(sourceDoc, settings);
|
|
57
|
+
return (_jsx(NitrogenPageClient, { pageId: String(page.id), pageData: page.nitrogenData || [], dynamicData: dynamicData, isBuilder: isBuilder, collection: collection, language: language }));
|
|
36
58
|
}
|
|
37
59
|
export default NitrogenWrapper;
|
package/dist/index.d.ts
CHANGED
|
@@ -34,6 +34,27 @@ export interface NitrogenConnectorPluginOptions {
|
|
|
34
34
|
* `users`).
|
|
35
35
|
*/
|
|
36
36
|
userCollection?: string;
|
|
37
|
+
/**
|
|
38
|
+
* Enables Payload-native localization for field data. When set (and the
|
|
39
|
+
* Payload config does not already configure `localization` itself), the
|
|
40
|
+
* plugin injects `localization: { locales, defaultLocale, fallback: true }`
|
|
41
|
+
* into the Payload config and marks eligible text fields (`title` on
|
|
42
|
+
* Nitrogen-enabled collections and on the plugin's own template collection)
|
|
43
|
+
* as `localized: true`. Localize your own custom fields yourself.
|
|
44
|
+
*
|
|
45
|
+
* IMPORTANT: the locales here must match the site languages configured in
|
|
46
|
+
* the Nitrogen settings (`nitrogenConfig.localization.languages`), and
|
|
47
|
+
* `defaultLocale` must match `defaultLanguage` — Payload stores the field
|
|
48
|
+
* translations, Nitrogen stores the builder-content translations, and the
|
|
49
|
+
* language codes are the join key.
|
|
50
|
+
*
|
|
51
|
+
* If your Payload config already has `localization` configured, that config
|
|
52
|
+
* is respected and this option does not override it.
|
|
53
|
+
*/
|
|
54
|
+
localization?: {
|
|
55
|
+
locales: string[];
|
|
56
|
+
defaultLocale: string;
|
|
57
|
+
};
|
|
37
58
|
}
|
|
38
59
|
export declare const nitrogenConnectorPlugin: (options?: NitrogenConnectorPluginOptions) => any;
|
|
39
60
|
export { NitrogenTemplates } from "./collections/NitrogenTemplates.js";
|
|
@@ -41,6 +62,7 @@ export { NitrogenSettings } from "./globals/NitrogenSettings.js";
|
|
|
41
62
|
export { NitrogenEditButton } from "./components/NitrogenEditButton.js";
|
|
42
63
|
export { NitrogenViewButton } from "./components/NitrogenViewButton.js";
|
|
43
64
|
export { buildDynamicData, getNitrogenSettings } from "./endpoints/helpers.js";
|
|
65
|
+
export { buildDynamicDataMeta, getRequestLanguage, resolveLocaleOptions, } from "./localization.js";
|
|
44
66
|
export { createCollectionEndpoints } from "./endpoints/collection-endpoints.js";
|
|
45
67
|
export { nitrogen } from "@nitrogenbuilder/client-core";
|
|
46
68
|
export type { ComponentSettings, ComponentSettingsToProps, } from "@nitrogenbuilder/types";
|
package/dist/index.js
CHANGED
|
@@ -13,6 +13,7 @@ import { createCollectionEndpoints } from "./endpoints/collection-endpoints.js";
|
|
|
13
13
|
import { createComponentInventoryEndpoints } from './endpoints/component-inventory.js';
|
|
14
14
|
import { batchEndpoints } from "./endpoints/batch.js";
|
|
15
15
|
import { sitemapEndpoints } from "./endpoints/sitemap.js";
|
|
16
|
+
import { createTranslationStatusEndpoints } from "./endpoints/translation-status.js";
|
|
16
17
|
import { createAgentAuthEndpoints } from "./endpoints/agent-auth.js";
|
|
17
18
|
import { registerCollection } from "./collection-registry.js";
|
|
18
19
|
import { deleteDocumentUsage, reindexDocumentUsage, syncComponentCatalog, } from './inventory/indexing.js';
|
|
@@ -38,12 +39,57 @@ const nitrogenRequiredFields = [
|
|
|
38
39
|
},
|
|
39
40
|
},
|
|
40
41
|
},
|
|
42
|
+
{
|
|
43
|
+
name: "nitrogenTranslationStatus",
|
|
44
|
+
type: "json",
|
|
45
|
+
admin: {
|
|
46
|
+
hidden: true,
|
|
47
|
+
description: "Per-language translation coverage, computed by Nitrogen on save",
|
|
48
|
+
},
|
|
49
|
+
},
|
|
41
50
|
];
|
|
51
|
+
/**
|
|
52
|
+
* Marks `title` text fields as `localized: true` (recursing into rows, tabs,
|
|
53
|
+
* groups, collapsibles). Fields that already declare `localized` explicitly
|
|
54
|
+
* are left untouched.
|
|
55
|
+
*/
|
|
56
|
+
function localizeTitleFields(fields) {
|
|
57
|
+
return fields.map((field) => {
|
|
58
|
+
const f = field;
|
|
59
|
+
if (f.type === "text" && f.name === "title" && f.localized === undefined) {
|
|
60
|
+
return { ...field, localized: true };
|
|
61
|
+
}
|
|
62
|
+
if (Array.isArray(f.fields)) {
|
|
63
|
+
return { ...field, fields: localizeTitleFields(f.fields) };
|
|
64
|
+
}
|
|
65
|
+
if (Array.isArray(f.tabs)) {
|
|
66
|
+
return {
|
|
67
|
+
...field,
|
|
68
|
+
tabs: f.tabs.map((tab) => ({
|
|
69
|
+
...tab,
|
|
70
|
+
fields: localizeTitleFields(tab.fields || []),
|
|
71
|
+
})),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
return field;
|
|
75
|
+
});
|
|
76
|
+
}
|
|
42
77
|
export const nitrogenConnectorPlugin = (options = {}) => (incomingConfig) => {
|
|
43
78
|
if (options.disabled) {
|
|
44
79
|
return incomingConfig;
|
|
45
80
|
}
|
|
46
81
|
const config = { ...incomingConfig };
|
|
82
|
+
// Payload-native localization for field data. Only injected when the host
|
|
83
|
+
// config doesn't configure localization itself — an existing config is
|
|
84
|
+
// always respected.
|
|
85
|
+
if (options.localization && !incomingConfig.localization) {
|
|
86
|
+
config.localization = {
|
|
87
|
+
locales: options.localization.locales,
|
|
88
|
+
defaultLocale: options.localization.defaultLocale,
|
|
89
|
+
fallback: true,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
const localizationActive = Boolean(config.localization);
|
|
47
93
|
// The auth collection that owns MCP agent credentials. Prefer the explicit
|
|
48
94
|
// option, else the first auth-enabled collection, else `users`.
|
|
49
95
|
const userCollectionSlug = options.userCollection ||
|
|
@@ -83,10 +129,19 @@ export const nitrogenConnectorPlugin = (options = {}) => (incomingConfig) => {
|
|
|
83
129
|
},
|
|
84
130
|
};
|
|
85
131
|
};
|
|
86
|
-
// Add Nitrogen templates collection
|
|
132
|
+
// Add Nitrogen templates collection. With localization active, template
|
|
133
|
+
// titles are localized (translated in the Payload admin's locale
|
|
134
|
+
// switcher); internal catalog/usage collections stay non-localized —
|
|
135
|
+
// their text fields are machine identifiers, not content.
|
|
136
|
+
const templatesCollection = localizationActive
|
|
137
|
+
? {
|
|
138
|
+
...NitrogenTemplates,
|
|
139
|
+
fields: localizeTitleFields(NitrogenTemplates.fields),
|
|
140
|
+
}
|
|
141
|
+
: NitrogenTemplates;
|
|
87
142
|
config.collections = [
|
|
88
143
|
...(config.collections || []),
|
|
89
|
-
withInventoryHooks(
|
|
144
|
+
withInventoryHooks(templatesCollection, 'nitrogen-templates'),
|
|
90
145
|
NitrogenComponentCatalog,
|
|
91
146
|
NitrogenComponentUsage,
|
|
92
147
|
];
|
|
@@ -103,6 +158,7 @@ export const nitrogenConnectorPlugin = (options = {}) => (incomingConfig) => {
|
|
|
103
158
|
...menuEndpoints,
|
|
104
159
|
...batchEndpoints,
|
|
105
160
|
...sitemapEndpoints,
|
|
161
|
+
...createTranslationStatusEndpoints(options.collections || []),
|
|
106
162
|
...createAgentAuthEndpoints(userCollectionSlug),
|
|
107
163
|
...createComponentInventoryEndpoints({
|
|
108
164
|
collections: inventoryCollections,
|
|
@@ -191,6 +247,16 @@ export const nitrogenConnectorPlugin = (options = {}) => (incomingConfig) => {
|
|
|
191
247
|
fields: [...existing.fields, ...fieldsToAdd],
|
|
192
248
|
};
|
|
193
249
|
}
|
|
250
|
+
// With localization active, the collection's title becomes localized so
|
|
251
|
+
// it can be translated via the Payload admin's native locale switcher.
|
|
252
|
+
// (Users localize their own custom fields themselves.)
|
|
253
|
+
if (localizationActive) {
|
|
254
|
+
const current = config.collections[existingIndex];
|
|
255
|
+
config.collections[existingIndex] = {
|
|
256
|
+
...current,
|
|
257
|
+
fields: localizeTitleFields(current.fields),
|
|
258
|
+
};
|
|
259
|
+
}
|
|
194
260
|
// Inject NitrogenEditButton admin component
|
|
195
261
|
const col = config.collections[existingIndex];
|
|
196
262
|
const adminConfig = col.admin || {};
|
|
@@ -301,6 +367,7 @@ export { NitrogenEditButton } from "./components/NitrogenEditButton.js";
|
|
|
301
367
|
export { NitrogenViewButton } from "./components/NitrogenViewButton.js";
|
|
302
368
|
// Helper exports for consumers building custom frontend routes
|
|
303
369
|
export { buildDynamicData, getNitrogenSettings } from "./endpoints/helpers.js";
|
|
370
|
+
export { buildDynamicDataMeta, getRequestLanguage, resolveLocaleOptions, } from "./localization.js";
|
|
304
371
|
// Collection endpoint factory for consumers who need custom endpoint generation
|
|
305
372
|
export { createCollectionEndpoints } from "./endpoints/collection-endpoints.js";
|
|
306
373
|
// Re-export @nitrogenbuilder packages for convenience
|
|
@@ -16,6 +16,8 @@ type ReindexResult = {
|
|
|
16
16
|
export declare function extractComponentUsageRecords(modules: unknown): ComponentUsageRecord[];
|
|
17
17
|
export declare function findAllDocs<T extends object>(payload: Payload, collection: string, options?: {
|
|
18
18
|
limit?: number;
|
|
19
|
+
/** e.g. 'all' to fetch every locale's value for localized fields */
|
|
20
|
+
locale?: string;
|
|
19
21
|
select?: Record<string, true>;
|
|
20
22
|
where?: Where;
|
|
21
23
|
}, req?: PayloadRequest): Promise<T[]>;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Localization support — locale threading for read endpoints, dynamic-data
|
|
3
|
+
* translation metadata, and per-language translation status for builder
|
|
4
|
+
* content.
|
|
5
|
+
*
|
|
6
|
+
* Two independent layers cooperate here:
|
|
7
|
+
*
|
|
8
|
+
* 1. **Payload-native localization** (field data). When the host project's
|
|
9
|
+
* Payload config has `localization` configured (either directly or injected
|
|
10
|
+
* from the plugin's `localization` option), eligible text fields are
|
|
11
|
+
* localized and read endpoints thread `?lang=` through to
|
|
12
|
+
* `payload.find`/`findByID` as `locale` + `fallbackLocale`.
|
|
13
|
+
* 2. **Nitrogen settings localization** (builder content). Site languages live
|
|
14
|
+
* in the `nitrogen-settings` global under `nitrogenConfig.localization`.
|
|
15
|
+
* Translatable prop values inside `nitrogenData` are stored language-keyed
|
|
16
|
+
* with the language as the OUTER key (`{ en: ..., es: ... }`); legacy bare
|
|
17
|
+
* values read as the default language.
|
|
18
|
+
*
|
|
19
|
+
* Everything is gated: with no localization configured anywhere, every helper
|
|
20
|
+
* returns null/empty and callers behave exactly as before.
|
|
21
|
+
*/
|
|
22
|
+
import type { Field, Payload, PayloadRequest, SanitizedCollectionConfig } from 'payload';
|
|
23
|
+
import type { ComponentManifestProp, DynamicDataMeta, LanguageStatus, LocalizationSettings } from '@nitrogenbuilder/types';
|
|
24
|
+
import type { NitrogenSettingsGlobal } from './types.js';
|
|
25
|
+
export interface PayloadLocaleConfig {
|
|
26
|
+
locales: string[];
|
|
27
|
+
defaultLocale: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Reads the sanitized Payload localization config at runtime. Returns null
|
|
31
|
+
* when the project has no Payload-level localization configured.
|
|
32
|
+
*/
|
|
33
|
+
export declare function getPayloadLocalization(payload: Payload): PayloadLocaleConfig | null;
|
|
34
|
+
/** Reads `?lang=` (alias `?locale=`) off a request URL. */
|
|
35
|
+
export declare function getRequestLanguage(req: PayloadRequest): string | null;
|
|
36
|
+
export interface LocaleQueryOptions {
|
|
37
|
+
locale?: string;
|
|
38
|
+
fallbackLocale?: string;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Turns a requested language into `locale`/`fallbackLocale` options for
|
|
42
|
+
* `payload.find`/`findByID`. Returns `{}` (default behavior) when no language
|
|
43
|
+
* was requested, the project has no Payload localization, or the language is
|
|
44
|
+
* not a configured locale.
|
|
45
|
+
*/
|
|
46
|
+
export declare function resolveLocaleOptions(payload: Payload, lang?: string | null): LocaleQueryOptions;
|
|
47
|
+
export declare function getCollectionConfig(payload: Payload, collectionSlug: string): SanitizedCollectionConfig | undefined;
|
|
48
|
+
/**
|
|
49
|
+
* Dot-paths of localized text-typed fields of a collection config. Walks
|
|
50
|
+
* groups, rows, collapsibles, and tabs; named groups/tabs contribute a path
|
|
51
|
+
* segment.
|
|
52
|
+
*/
|
|
53
|
+
export declare function getLocalizedTextFieldPaths(fields: Field[] | undefined, prefix?: string): string[];
|
|
54
|
+
/**
|
|
55
|
+
* The site language config from the `nitrogen-settings` global. Null when
|
|
56
|
+
* localization is absent or disabled — callers must treat null as
|
|
57
|
+
* "no localization behavior at all".
|
|
58
|
+
*/
|
|
59
|
+
export declare function getLocalizationSettings(settings: NitrogenSettingsGlobal): LocalizationSettings | null;
|
|
60
|
+
/**
|
|
61
|
+
* Fetches a doc with every locale's value for localized fields (one
|
|
62
|
+
* `locale: 'all'` query). Returns null when the project has no Payload
|
|
63
|
+
* localization configured or the doc can't be read — advisory callers keep
|
|
64
|
+
* their default behavior in that case.
|
|
65
|
+
*/
|
|
66
|
+
export declare function fetchLocaleAllDoc(payload: Payload, collectionSlug: string, docId: string | number): Promise<Record<string, unknown> | null>;
|
|
67
|
+
/**
|
|
68
|
+
* The default-locale title from a `locale: 'all'` doc, for editor-facing
|
|
69
|
+
* single-doc responses. The editor edits default-language field data only
|
|
70
|
+
* (the CMS admin owns field translations), so the `title` it displays and
|
|
71
|
+
* PATCHes back on save must never be a locale-resolved one. Returns null when
|
|
72
|
+
* there is nothing to override (no localization, title not localized, or no
|
|
73
|
+
* stored title) — callers then keep the response title as-is.
|
|
74
|
+
*/
|
|
75
|
+
export declare function getDefaultLocaleTitle(payload: Payload, localeAllDoc: Record<string, unknown> | null): string | null;
|
|
76
|
+
/**
|
|
77
|
+
* Builds the connector-provided metadata the editor uses to badge
|
|
78
|
+
* untranslated CMS fields. Eligible keys are the localized text-typed fields
|
|
79
|
+
* of the collection config; translated keys per language are the fields whose
|
|
80
|
+
* locale-specific value exists (checked via one `locale: 'all'` fetch, or a
|
|
81
|
+
* caller-preloaded `localeAllDoc` to avoid a duplicate query).
|
|
82
|
+
*
|
|
83
|
+
* Returns null when the project has no Payload localization configured, so
|
|
84
|
+
* callers can attach `dynamic_data_meta` conditionally with zero change to
|
|
85
|
+
* the default response shape.
|
|
86
|
+
*/
|
|
87
|
+
export declare function buildDynamicDataMeta(payload: Payload, collectionSlug: string, docId?: string | number, localeAllDoc?: Record<string, unknown> | null): Promise<DynamicDataMeta | null>;
|
|
88
|
+
type CatalogPropDef = ComponentManifestProp & {
|
|
89
|
+
translatable?: boolean;
|
|
90
|
+
};
|
|
91
|
+
/**
|
|
92
|
+
* componentName → group key → propKey → prop definition. Module prop values
|
|
93
|
+
* are stored group-keyed (`props[groupKey][propKey]`, mirroring the renderer's
|
|
94
|
+
* `spreadProps`), so the group level is preserved for lookups during the walk.
|
|
95
|
+
*/
|
|
96
|
+
export type TranslatablePropDefs = Map<string, Record<string, Record<string, CatalogPropDef>>>;
|
|
97
|
+
/**
|
|
98
|
+
* Loads component prop definitions from the nitrogen-component-catalog
|
|
99
|
+
* collection so translatable props can be identified precisely. Returns an
|
|
100
|
+
* empty map when the catalog is unavailable — the walk then falls back to the
|
|
101
|
+
* lang-map heuristic.
|
|
102
|
+
*/
|
|
103
|
+
export declare function loadTranslatablePropDefs(payload: Payload): Promise<TranslatablePropDefs>;
|
|
104
|
+
export interface ComputeTranslationStatusArgs {
|
|
105
|
+
payload: Payload;
|
|
106
|
+
collectionSlug: string;
|
|
107
|
+
docId: string | number;
|
|
108
|
+
nitrogenData: unknown;
|
|
109
|
+
localization: LocalizationSettings;
|
|
110
|
+
/** Preloaded catalog defs (avoids a re-fetch when batching). */
|
|
111
|
+
propDefs?: TranslatablePropDefs;
|
|
112
|
+
/** Preloaded `locale: 'all'` doc (avoids a re-fetch when batching). */
|
|
113
|
+
localeAllDoc?: Record<string, unknown> | null;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Computes per-language translation status for one page/template. Returns a
|
|
117
|
+
* `{ [langCode]: LanguageStatus }` map covering every configured non-default
|
|
118
|
+
* language, or null when there is nothing to compute.
|
|
119
|
+
*/
|
|
120
|
+
export declare function computeDocTranslationStatus(args: ComputeTranslationStatusArgs): Promise<Record<string, LanguageStatus> | null>;
|
|
121
|
+
export {};
|