strapi-plugin-hubspot 0.14.0 → 0.16.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/CHANGELOG.md +22 -0
- package/README.md +39 -15
- package/dist/_chunks/{Forms-ws6d8rdC.mjs → Forms-6EoEYzAc.mjs} +26 -5
- package/dist/_chunks/{Forms-Cch-7zei.js → Forms-BW_zGc1P.js} +26 -5
- package/dist/_chunks/{HubspotFormInput-18pWTITT.mjs → HubspotFormInput-V5w4y1fb.mjs} +1 -1
- package/dist/_chunks/{HubspotFormInput-M2l_8w_e.js → HubspotFormInput-oMhm1UJm.js} +1 -1
- package/dist/_chunks/{HubspotObjectInput-BDO99qXs.js → HubspotObjectInput-Bmo6YQgs.js} +3 -3
- package/dist/_chunks/{HubspotObjectInput-DshusXZP.mjs → HubspotObjectInput-DhsnSguG.mjs} +3 -3
- package/dist/_chunks/{HubspotPropertyInput-C-kHDgwx.mjs → HubspotPropertyInput-CrYP4pc0.mjs} +3 -3
- package/dist/_chunks/{HubspotPropertyInput-XGnH2tHn.js → HubspotPropertyInput-luFfnxqy.js} +3 -3
- package/dist/_chunks/{Settings-CRnsu6ob.js → Settings-B3A22i7Z.js} +204 -35
- package/dist/_chunks/{Settings-Bm7WkzK1.mjs → Settings-CjcWj9I6.mjs} +205 -36
- package/dist/_chunks/{en-BXMU5CjT.js → en-C7ls2EUl.js} +28 -6
- package/dist/_chunks/{en-DKV-8FWP.mjs → en-D6GHgMOt.mjs} +28 -6
- package/dist/_chunks/{fr-GB6T3ZyU.mjs → fr-CfohMY8n.mjs} +27 -5
- package/dist/_chunks/{fr-Dx4XmZ4X.js → fr-pOP8ZXqM.js} +27 -5
- package/dist/_chunks/{index-CPVfElYB.mjs → index-7cL9PRh1.mjs} +6 -6
- package/dist/_chunks/{index-BlaG8oIq.js → index-CodpLKZx.js} +6 -6
- package/dist/_chunks/{objectLabels-CPc21Tdd.js → objectLabels-CSWGIgNb.js} +1 -1
- package/dist/_chunks/{objectLabels-6OUnIDB5.mjs → objectLabels-Dnj14fsp.mjs} +1 -1
- package/dist/_chunks/{useHubspotSchema-qCUs2gIX.mjs → useHubspotSchema-BsmQgJgx.mjs} +1 -1
- package/dist/_chunks/{useHubspotSchema-0MvCM1AC.js → useHubspotSchema-DiRN3HrN.js} +1 -1
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/server/index.js +301 -15
- package/dist/server/index.mjs +301 -15
- package/dist/server/src/__tests__/formSync.test.d.ts +1 -0
- package/dist/server/src/__tests__/settings.test.d.ts +1 -0
- package/dist/server/src/formSync.d.ts +37 -0
- package/dist/server/src/forms.d.ts +6 -8
- package/dist/server/src/hsforms.d.ts +8 -0
- package/dist/server/src/importHubspot.d.ts +4 -0
- package/dist/server/src/index.d.ts +11 -1
- package/dist/server/src/settings.d.ts +65 -5
- package/package.json +1 -1
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
import { u as useIntl } from "./index-CEh8vkxY.mjs";
|
|
4
|
-
import { Flex, Divider, Typography, Button, Box, Link, Badge, Loader, Field } from "@strapi/design-system";
|
|
4
|
+
import { Flex, Divider, Typography, Button, Box, Link, Badge, Loader, Field, SingleSelect, SingleSelectOption, Checkbox } from "@strapi/design-system";
|
|
5
5
|
import { useFetchClient } from "@strapi/strapi/admin";
|
|
6
|
-
import { g as getTranslation, P as PLUGIN_ID } from "./index-
|
|
6
|
+
import { g as getTranslation, P as PLUGIN_ID } from "./index-7cL9PRh1.mjs";
|
|
7
7
|
import { Link as Link$1 } from "react-router-dom";
|
|
8
|
-
import { o as objectLabel } from "./objectLabels-
|
|
8
|
+
import { o as objectLabel } from "./objectLabels-Dnj14fsp.mjs";
|
|
9
9
|
const AuditSection = ({ configured }) => {
|
|
10
10
|
const intl = useIntl();
|
|
11
11
|
const { formatMessage } = intl;
|
|
@@ -172,19 +172,37 @@ const FailuresSection = ({ configured }) => {
|
|
|
172
172
|
) : null
|
|
173
173
|
] });
|
|
174
174
|
};
|
|
175
|
+
const REGIONS = ["eu1", "na1"];
|
|
175
176
|
const HubspotSettings = () => {
|
|
176
177
|
const { formatMessage } = useIntl();
|
|
177
178
|
const { get, put, del } = useFetchClient();
|
|
178
179
|
const [settings, setSettings] = React.useState(null);
|
|
179
180
|
const [apiKey, setApiKey] = React.useState("");
|
|
181
|
+
const [portalId, setPortalId] = React.useState("");
|
|
182
|
+
const [region, setRegion] = React.useState("eu1");
|
|
183
|
+
const [defaultFormId, setDefaultFormId] = React.useState("");
|
|
184
|
+
const [submissionMode, setSubmissionMode] = React.useState("auto");
|
|
185
|
+
const [writeExtraProperties, setWriteExtraProperties] = React.useState(true);
|
|
186
|
+
const [syncFieldsOnPublish, setSyncFieldsOnPublish] = React.useState(false);
|
|
187
|
+
const [forms, setForms] = React.useState([]);
|
|
180
188
|
const [busy, setBusy] = React.useState(false);
|
|
181
189
|
const [feedback, setFeedback] = React.useState(
|
|
182
190
|
null
|
|
183
191
|
);
|
|
184
192
|
const t = (id, defaultMessage, values) => formatMessage({ id: getTranslation(id), defaultMessage }, values);
|
|
193
|
+
const apply = (data) => {
|
|
194
|
+
setSettings(data);
|
|
195
|
+
setPortalId(data.portalId ?? "");
|
|
196
|
+
setRegion(data.region || "eu1");
|
|
197
|
+
setDefaultFormId(data.defaultFormId ?? "");
|
|
198
|
+
setSubmissionMode(data.submissionMode === "crm" || data.submissionMode === "forms" ? data.submissionMode : "auto");
|
|
199
|
+
setWriteExtraProperties(data.writeExtraProperties !== false);
|
|
200
|
+
setSyncFieldsOnPublish(data.syncFieldsOnPublish === true);
|
|
201
|
+
setForms(Array.isArray(data.forms) ? data.forms : []);
|
|
202
|
+
};
|
|
185
203
|
const load = React.useCallback(async () => {
|
|
186
204
|
const { data } = await get(`/${PLUGIN_ID}/settings`);
|
|
187
|
-
|
|
205
|
+
apply(data);
|
|
188
206
|
}, [get]);
|
|
189
207
|
React.useEffect(() => {
|
|
190
208
|
load().catch(
|
|
@@ -195,12 +213,20 @@ const HubspotSettings = () => {
|
|
|
195
213
|
setBusy(true);
|
|
196
214
|
setFeedback(null);
|
|
197
215
|
try {
|
|
198
|
-
|
|
199
|
-
|
|
216
|
+
await put(`/${PLUGIN_ID}/settings`, {
|
|
217
|
+
...apiKey.trim() ? { apiKey: apiKey.trim() } : {},
|
|
218
|
+
portalId,
|
|
219
|
+
region,
|
|
220
|
+
defaultFormId,
|
|
221
|
+
submissionMode,
|
|
222
|
+
writeExtraProperties,
|
|
223
|
+
syncFieldsOnPublish
|
|
224
|
+
});
|
|
200
225
|
setApiKey("");
|
|
201
|
-
|
|
226
|
+
await load();
|
|
227
|
+
setFeedback({ tone: "success", text: t("settings.saved", "Settings saved.") });
|
|
202
228
|
} catch {
|
|
203
|
-
setFeedback({ tone: "danger", text: t("settings.save-error", "Could not save
|
|
229
|
+
setFeedback({ tone: "danger", text: t("settings.save-error", "Could not save settings.") });
|
|
204
230
|
} finally {
|
|
205
231
|
setBusy(false);
|
|
206
232
|
}
|
|
@@ -209,9 +235,9 @@ const HubspotSettings = () => {
|
|
|
209
235
|
setBusy(true);
|
|
210
236
|
setFeedback(null);
|
|
211
237
|
try {
|
|
212
|
-
|
|
213
|
-
setSettings(data);
|
|
238
|
+
await del(`/${PLUGIN_ID}/settings`);
|
|
214
239
|
setApiKey("");
|
|
240
|
+
await load();
|
|
215
241
|
setFeedback({ tone: "success", text: t("settings.removed", "Key removed.") });
|
|
216
242
|
} catch {
|
|
217
243
|
setFeedback({ tone: "danger", text: t("settings.remove-error", "Could not remove the key.") });
|
|
@@ -234,6 +260,7 @@ const HubspotSettings = () => {
|
|
|
234
260
|
})
|
|
235
261
|
} : { tone: "danger", text: t("settings.test-no-key", "No key configured.") }
|
|
236
262
|
);
|
|
263
|
+
if (data.configured) await load();
|
|
237
264
|
} catch {
|
|
238
265
|
setFeedback({
|
|
239
266
|
tone: "danger",
|
|
@@ -251,44 +278,186 @@ const HubspotSettings = () => {
|
|
|
251
278
|
config: t("settings.source.config", "config/plugins.ts"),
|
|
252
279
|
env: t("settings.source.env", "environment variable")
|
|
253
280
|
};
|
|
281
|
+
const sourceHint = (source) => source && source !== "settings" ? /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: t("settings.source", "source: {source}", { source: sourceLabel[source] }) }) : null;
|
|
282
|
+
const regionOptions = REGIONS.includes(region) ? [...REGIONS] : [region, ...REGIONS];
|
|
254
283
|
return /* @__PURE__ */ jsx(Box, { padding: 8, children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 6, children: [
|
|
255
284
|
/* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", gap: 2, children: [
|
|
256
285
|
/* @__PURE__ */ jsx(Typography, { variant: "alpha", children: "HubSpot" }),
|
|
257
286
|
/* @__PURE__ */ jsx(Typography, { variant: "epsilon", textColor: "neutral600", children: t(
|
|
258
287
|
"settings.subtitle",
|
|
259
|
-
"
|
|
288
|
+
"Private app token and the HubSpot account that receives form conversions. Switch test → production here — nothing is hardcoded."
|
|
260
289
|
) })
|
|
261
290
|
] }),
|
|
262
291
|
/* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", children: [
|
|
263
292
|
/* @__PURE__ */ jsx(Badge, { active: settings.configured, children: settings.configured ? t("settings.configured", "Configured {hint}", { hint: settings.hint }) : t("settings.not-configured", "Not configured") }),
|
|
264
293
|
settings.keySource ? /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: t("settings.source", "source: {source}", { source: sourceLabel[settings.keySource] }) }) : null
|
|
265
294
|
] }),
|
|
266
|
-
/* @__PURE__ */ jsx(Box, { maxWidth: "32rem", children: /* @__PURE__ */ jsxs(
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
295
|
+
/* @__PURE__ */ jsx(Box, { maxWidth: "32rem", children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
|
|
296
|
+
/* @__PURE__ */ jsxs(
|
|
297
|
+
Field.Root,
|
|
298
|
+
{
|
|
299
|
+
name: "apiKey",
|
|
300
|
+
hint: t(
|
|
301
|
+
"settings.key.hint",
|
|
302
|
+
"A key entered here overrides config/plugins.ts and HUBSPOT_API_KEY."
|
|
303
|
+
),
|
|
304
|
+
children: [
|
|
305
|
+
/* @__PURE__ */ jsx(Field.Label, { children: t("settings.key.label", "Private app token") }),
|
|
306
|
+
/* @__PURE__ */ jsx(
|
|
307
|
+
Field.Input,
|
|
308
|
+
{
|
|
309
|
+
type: "password",
|
|
310
|
+
value: apiKey,
|
|
311
|
+
autoComplete: "off",
|
|
312
|
+
placeholder: settings.configured ? t("settings.key.placeholder.set", "•••••••• (leave empty to keep)") : t("settings.key.placeholder.empty", "pat-eu1-…"),
|
|
313
|
+
onChange: (e) => setApiKey(e.target.value)
|
|
314
|
+
}
|
|
315
|
+
),
|
|
316
|
+
/* @__PURE__ */ jsx(Field.Hint, {})
|
|
317
|
+
]
|
|
318
|
+
}
|
|
319
|
+
),
|
|
320
|
+
/* @__PURE__ */ jsxs(
|
|
321
|
+
Field.Root,
|
|
322
|
+
{
|
|
323
|
+
name: "portalId",
|
|
324
|
+
hint: t(
|
|
325
|
+
"settings.portal.hint",
|
|
326
|
+
"HubSpot account id (Settings → Account → Account setup). Test portal today, production later."
|
|
327
|
+
),
|
|
328
|
+
children: [
|
|
329
|
+
/* @__PURE__ */ jsx(Field.Label, { children: t("settings.portal.label", "Portal ID") }),
|
|
330
|
+
/* @__PURE__ */ jsx(
|
|
331
|
+
Field.Input,
|
|
332
|
+
{
|
|
333
|
+
type: "text",
|
|
334
|
+
value: portalId,
|
|
335
|
+
autoComplete: "off",
|
|
336
|
+
placeholder: "148991818",
|
|
337
|
+
onChange: (e) => setPortalId(e.target.value)
|
|
338
|
+
}
|
|
339
|
+
),
|
|
340
|
+
/* @__PURE__ */ jsx(Field.Hint, {}),
|
|
341
|
+
sourceHint(settings.portalSource)
|
|
342
|
+
]
|
|
343
|
+
}
|
|
344
|
+
),
|
|
345
|
+
/* @__PURE__ */ jsxs(Field.Root, { name: "region", children: [
|
|
346
|
+
/* @__PURE__ */ jsx(Field.Label, { children: t("settings.region.label", "Region") }),
|
|
347
|
+
/* @__PURE__ */ jsx(
|
|
348
|
+
SingleSelect,
|
|
349
|
+
{
|
|
350
|
+
value: region,
|
|
351
|
+
onChange: (value) => setRegion(String(value)),
|
|
352
|
+
children: regionOptions.map((r) => /* @__PURE__ */ jsx(SingleSelectOption, { value: r, children: r === "eu1" ? t("settings.region.eu1", "Europe (eu1)") : r === "na1" ? t("settings.region.na1", "North America (na1)") : r }, r))
|
|
353
|
+
}
|
|
273
354
|
),
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
onChange: (e) => setApiKey(e.target.value)
|
|
284
|
-
}
|
|
355
|
+
sourceHint(settings.regionSource)
|
|
356
|
+
] }),
|
|
357
|
+
/* @__PURE__ */ jsxs(
|
|
358
|
+
Field.Root,
|
|
359
|
+
{
|
|
360
|
+
name: "defaultFormId",
|
|
361
|
+
hint: t(
|
|
362
|
+
"settings.form.hint",
|
|
363
|
+
"Marketing form that receives submissions when a builder form doesn't pick its own. Create the form in HubSpot, then pick it here."
|
|
285
364
|
),
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
365
|
+
children: [
|
|
366
|
+
/* @__PURE__ */ jsx(Field.Label, { children: t("settings.form.label", "Default marketing form") }),
|
|
367
|
+
forms.length ? /* @__PURE__ */ jsxs(
|
|
368
|
+
SingleSelect,
|
|
369
|
+
{
|
|
370
|
+
value: defaultFormId,
|
|
371
|
+
placeholder: t("settings.form.placeholder", "Pick a form of the connected portal"),
|
|
372
|
+
onChange: (value) => setDefaultFormId(String(value)),
|
|
373
|
+
children: [
|
|
374
|
+
/* @__PURE__ */ jsx(SingleSelectOption, { value: "", children: t("settings.form.none", "None — CRM upsert only") }),
|
|
375
|
+
defaultFormId && !forms.some((f) => f.id === defaultFormId) && /* @__PURE__ */ jsx(SingleSelectOption, { value: defaultFormId, children: defaultFormId }),
|
|
376
|
+
forms.map((f) => /* @__PURE__ */ jsx(SingleSelectOption, { value: f.id, children: f.name }, f.id))
|
|
377
|
+
]
|
|
378
|
+
}
|
|
379
|
+
) : /* @__PURE__ */ jsx(
|
|
380
|
+
Field.Input,
|
|
381
|
+
{
|
|
382
|
+
type: "text",
|
|
383
|
+
value: defaultFormId,
|
|
384
|
+
autoComplete: "off",
|
|
385
|
+
placeholder: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
|
|
386
|
+
onChange: (e) => setDefaultFormId(e.target.value.trim())
|
|
387
|
+
}
|
|
388
|
+
),
|
|
389
|
+
/* @__PURE__ */ jsx(Field.Hint, {}),
|
|
390
|
+
sourceHint(settings.formSource)
|
|
391
|
+
]
|
|
392
|
+
}
|
|
393
|
+
),
|
|
394
|
+
/* @__PURE__ */ jsx(Typography, { variant: "delta", children: t("settings.policy.title", "How submissions reach HubSpot") }),
|
|
395
|
+
/* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: t(
|
|
396
|
+
"settings.policy.hint",
|
|
397
|
+
"Pick the policy that matches this portal. Defaults stay safe for every install: conversions when a form is linked, leftover answers still written on the contact, HubSpot forms never mutated unless you ask."
|
|
398
|
+
) }),
|
|
399
|
+
/* @__PURE__ */ jsxs(
|
|
400
|
+
Field.Root,
|
|
401
|
+
{
|
|
402
|
+
name: "submissionMode",
|
|
403
|
+
hint: t(
|
|
404
|
+
"settings.mode.hint",
|
|
405
|
+
"Automatic uses the marketing form when one is linked, otherwise a CRM upsert. CRM-only never counts as a conversion. Forms-only prefers the Forms API and falls back to the CRM if HubSpot refuses the submit."
|
|
406
|
+
),
|
|
407
|
+
children: [
|
|
408
|
+
/* @__PURE__ */ jsx(Field.Label, { children: t("settings.mode.label", "Submission path") }),
|
|
409
|
+
/* @__PURE__ */ jsxs(
|
|
410
|
+
SingleSelect,
|
|
411
|
+
{
|
|
412
|
+
value: submissionMode,
|
|
413
|
+
onChange: (value) => {
|
|
414
|
+
const next = String(value);
|
|
415
|
+
if (next === "crm" || next === "forms" || next === "auto") setSubmissionMode(next);
|
|
416
|
+
},
|
|
417
|
+
children: [
|
|
418
|
+
/* @__PURE__ */ jsx(SingleSelectOption, { value: "auto", children: t("settings.mode.auto", "Automatic — form conversion if linked, else CRM") }),
|
|
419
|
+
/* @__PURE__ */ jsx(SingleSelectOption, { value: "forms", children: t("settings.mode.forms", "Marketing form — native HubSpot conversions") }),
|
|
420
|
+
/* @__PURE__ */ jsx(SingleSelectOption, { value: "crm", children: t("settings.mode.crm", "CRM only — upsert the contact, no form conversion") })
|
|
421
|
+
]
|
|
422
|
+
}
|
|
423
|
+
),
|
|
424
|
+
/* @__PURE__ */ jsx(Field.Hint, {})
|
|
425
|
+
]
|
|
426
|
+
}
|
|
427
|
+
),
|
|
428
|
+
/* @__PURE__ */ jsx(
|
|
429
|
+
Checkbox,
|
|
430
|
+
{
|
|
431
|
+
checked: writeExtraProperties,
|
|
432
|
+
onCheckedChange: (checked) => setWriteExtraProperties(checked === true),
|
|
433
|
+
children: t(
|
|
434
|
+
"settings.extra.label",
|
|
435
|
+
"After a conversion, also write mapped contact fields that the HubSpot form doesn't have"
|
|
436
|
+
)
|
|
437
|
+
}
|
|
438
|
+
),
|
|
439
|
+
/* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: t(
|
|
440
|
+
"settings.extra.hint",
|
|
441
|
+
"The Forms API drops unknown fields (they 400 the submit). With this on, leftovers still land on the contact. Turn it off if HubSpot must only receive what the marketing form declares."
|
|
442
|
+
) }),
|
|
443
|
+
/* @__PURE__ */ jsx(
|
|
444
|
+
Checkbox,
|
|
445
|
+
{
|
|
446
|
+
checked: syncFieldsOnPublish,
|
|
447
|
+
onCheckedChange: (checked) => setSyncFieldsOnPublish(checked === true),
|
|
448
|
+
children: t(
|
|
449
|
+
"settings.sync.label",
|
|
450
|
+
"On publish, add mapped contact fields that are missing on the HubSpot form"
|
|
451
|
+
)
|
|
452
|
+
}
|
|
453
|
+
),
|
|
454
|
+
/* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: t(
|
|
455
|
+
"settings.sync.hint",
|
|
456
|
+
"Strapi-first installs: a field added here appears on the HubSpot form next publish. HubSpot-first installs should leave this off — importing a form already carries its fields. Properties themselves are never created; map to ones that exist in the portal."
|
|
457
|
+
) })
|
|
458
|
+
] }) }),
|
|
290
459
|
/* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
|
291
|
-
/* @__PURE__ */ jsx(Button, { onClick: save, loading: busy,
|
|
460
|
+
/* @__PURE__ */ jsx(Button, { onClick: save, loading: busy, children: t("settings.save", "Save") }),
|
|
292
461
|
/* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: test, loading: busy, disabled: !settings.configured, children: t("settings.test", "Test connection") }),
|
|
293
462
|
/* @__PURE__ */ jsx(
|
|
294
463
|
Button,
|
|
@@ -297,7 +466,7 @@ const HubspotSettings = () => {
|
|
|
297
466
|
onClick: remove,
|
|
298
467
|
loading: busy,
|
|
299
468
|
disabled: settings.keySource !== "settings",
|
|
300
|
-
children: t("settings.remove", "Remove")
|
|
469
|
+
children: t("settings.remove", "Remove key")
|
|
301
470
|
}
|
|
302
471
|
)
|
|
303
472
|
] }),
|
|
@@ -311,7 +480,7 @@ const HubspotSettings = () => {
|
|
|
311
480
|
) : null,
|
|
312
481
|
/* @__PURE__ */ jsx(Box, { paddingTop: 4, children: /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: t(
|
|
313
482
|
"settings.scopes",
|
|
314
|
-
"The token needs
|
|
483
|
+
"The token needs crm.schemas.contacts.read, crm.schemas.companies.read and forms (to list and submit marketing forms). The token is never returned to the browser."
|
|
315
484
|
) }) }),
|
|
316
485
|
/* @__PURE__ */ jsx(AuditSection, { configured: settings.configured }),
|
|
317
486
|
/* @__PURE__ */ jsx(FailuresSection, { configured: settings.configured })
|
|
@@ -30,7 +30,18 @@ const en = {
|
|
|
30
30
|
"picker.refresh": "Refresh the properties from HubSpot",
|
|
31
31
|
"picker.import": "Import the {count} options from HubSpot",
|
|
32
32
|
"picker.imported": "Options imported — save to keep them.",
|
|
33
|
-
"settings.subtitle": "
|
|
33
|
+
"settings.subtitle": "Private app token, HubSpot account, and how submissions reach the CRM. Switch test → production here — nothing is hardcoded.",
|
|
34
|
+
"settings.policy.title": "How submissions reach HubSpot",
|
|
35
|
+
"settings.policy.hint": "Pick the policy that matches this portal. Defaults stay safe for every install: conversions when a form is linked, leftover answers still written on the contact, HubSpot forms never mutated unless you ask.",
|
|
36
|
+
"settings.mode.label": "Submission path",
|
|
37
|
+
"settings.mode.hint": "Automatic uses the marketing form when one is linked, otherwise a CRM upsert. CRM-only never counts as a conversion. Forms-only prefers the Forms API and falls back to the CRM if HubSpot refuses the submit.",
|
|
38
|
+
"settings.mode.auto": "Automatic — form conversion if linked, else CRM",
|
|
39
|
+
"settings.mode.forms": "Marketing form — native HubSpot conversions",
|
|
40
|
+
"settings.mode.crm": "CRM only — upsert the contact, no form conversion",
|
|
41
|
+
"settings.extra.label": "After a conversion, also write mapped contact fields that the HubSpot form doesn't have",
|
|
42
|
+
"settings.extra.hint": "The Forms API drops unknown fields (they 400 the submit). With this on, leftovers still land on the contact. Turn it off if HubSpot must only receive what the marketing form declares.",
|
|
43
|
+
"settings.sync.label": "On publish, add mapped contact fields that are missing on the HubSpot form",
|
|
44
|
+
"settings.sync.hint": "Strapi-first installs: a field added here appears on the HubSpot form next publish. HubSpot-first installs should leave this off — importing a form already carries its fields. Properties themselves are never created; map to ones that exist in the portal.",
|
|
34
45
|
"settings.configured": "Configured {hint}",
|
|
35
46
|
"settings.not-configured": "Not configured",
|
|
36
47
|
"settings.source": "source: {source}",
|
|
@@ -38,22 +49,31 @@ const en = {
|
|
|
38
49
|
"settings.source.config": "config/plugins.ts",
|
|
39
50
|
"settings.source.env": "environment variable",
|
|
40
51
|
"settings.key.label": "Private app token",
|
|
41
|
-
"settings.key.hint": "A key entered here overrides
|
|
52
|
+
"settings.key.hint": "A key entered here overrides config/plugins.ts and HUBSPOT_API_KEY.",
|
|
42
53
|
"settings.key.placeholder.set": "•••••••• (leave empty to keep)",
|
|
43
54
|
"settings.key.placeholder.empty": "pat-eu1-…",
|
|
55
|
+
"settings.portal.label": "Portal ID",
|
|
56
|
+
"settings.portal.hint": "HubSpot account id (Settings → Account → Account setup). Test portal today, production later.",
|
|
57
|
+
"settings.region.label": "Region",
|
|
58
|
+
"settings.region.eu1": "Europe (eu1)",
|
|
59
|
+
"settings.region.na1": "North America (na1)",
|
|
60
|
+
"settings.form.label": "Default marketing form",
|
|
61
|
+
"settings.form.hint": "Marketing form that receives submissions when a builder form doesn't pick its own. Create the form in HubSpot, then pick it here.",
|
|
62
|
+
"settings.form.placeholder": "Pick a form of the connected portal",
|
|
63
|
+
"settings.form.none": "None — CRM upsert only",
|
|
44
64
|
"settings.save": "Save",
|
|
45
65
|
"settings.test": "Test connection",
|
|
46
|
-
"settings.remove": "Remove",
|
|
66
|
+
"settings.remove": "Remove key",
|
|
47
67
|
"settings.loading": "Loading…",
|
|
48
68
|
"settings.load-error": "Could not load settings.",
|
|
49
|
-
"settings.saved": "
|
|
50
|
-
"settings.save-error": "Could not save
|
|
69
|
+
"settings.saved": "Settings saved.",
|
|
70
|
+
"settings.save-error": "Could not save settings.",
|
|
51
71
|
"settings.removed": "Key removed.",
|
|
52
72
|
"settings.remove-error": "Could not remove the key.",
|
|
53
73
|
"settings.test-ok": "Connection established — {count} readable properties.",
|
|
54
74
|
"settings.test-no-key": "No key configured.",
|
|
55
75
|
"settings.test-error": "HubSpot unreachable — invalid or revoked key?",
|
|
56
|
-
"settings.scopes": "The token needs
|
|
76
|
+
"settings.scopes": "The token needs crm.schemas.contacts.read, crm.schemas.companies.read and forms (to list, submit, and optionally update marketing forms). The token is never returned to the browser.",
|
|
57
77
|
"audit.title": "Mapping audit",
|
|
58
78
|
"audit.subtitle": "Scans every entry of the validated content types and lists the mappings the portal would reject today — including properties deleted in HubSpot since they were saved.",
|
|
59
79
|
"audit.run": "Run the audit",
|
|
@@ -113,6 +133,8 @@ const en = {
|
|
|
113
133
|
"editor.invalid": "The structure has problems — see the flagged cards.",
|
|
114
134
|
"editor.publish": "Publish",
|
|
115
135
|
"editor.published": "Form published.",
|
|
136
|
+
"editor.published-synced": "Form published. {count, plural, one {# field added} other {# fields added}} to the HubSpot form.",
|
|
137
|
+
"editor.published-sync-warn": "Form published. HubSpot field sync failed: {error}",
|
|
116
138
|
"editor.publish-blocked": "Publishing is blocked — fix the flagged mappings first.",
|
|
117
139
|
"editor.unpublish": "Unpublish",
|
|
118
140
|
"editor.unpublished": "Form unpublished.",
|
|
@@ -28,7 +28,18 @@ const en = {
|
|
|
28
28
|
"picker.refresh": "Refresh the properties from HubSpot",
|
|
29
29
|
"picker.import": "Import the {count} options from HubSpot",
|
|
30
30
|
"picker.imported": "Options imported — save to keep them.",
|
|
31
|
-
"settings.subtitle": "
|
|
31
|
+
"settings.subtitle": "Private app token, HubSpot account, and how submissions reach the CRM. Switch test → production here — nothing is hardcoded.",
|
|
32
|
+
"settings.policy.title": "How submissions reach HubSpot",
|
|
33
|
+
"settings.policy.hint": "Pick the policy that matches this portal. Defaults stay safe for every install: conversions when a form is linked, leftover answers still written on the contact, HubSpot forms never mutated unless you ask.",
|
|
34
|
+
"settings.mode.label": "Submission path",
|
|
35
|
+
"settings.mode.hint": "Automatic uses the marketing form when one is linked, otherwise a CRM upsert. CRM-only never counts as a conversion. Forms-only prefers the Forms API and falls back to the CRM if HubSpot refuses the submit.",
|
|
36
|
+
"settings.mode.auto": "Automatic — form conversion if linked, else CRM",
|
|
37
|
+
"settings.mode.forms": "Marketing form — native HubSpot conversions",
|
|
38
|
+
"settings.mode.crm": "CRM only — upsert the contact, no form conversion",
|
|
39
|
+
"settings.extra.label": "After a conversion, also write mapped contact fields that the HubSpot form doesn't have",
|
|
40
|
+
"settings.extra.hint": "The Forms API drops unknown fields (they 400 the submit). With this on, leftovers still land on the contact. Turn it off if HubSpot must only receive what the marketing form declares.",
|
|
41
|
+
"settings.sync.label": "On publish, add mapped contact fields that are missing on the HubSpot form",
|
|
42
|
+
"settings.sync.hint": "Strapi-first installs: a field added here appears on the HubSpot form next publish. HubSpot-first installs should leave this off — importing a form already carries its fields. Properties themselves are never created; map to ones that exist in the portal.",
|
|
32
43
|
"settings.configured": "Configured {hint}",
|
|
33
44
|
"settings.not-configured": "Not configured",
|
|
34
45
|
"settings.source": "source: {source}",
|
|
@@ -36,22 +47,31 @@ const en = {
|
|
|
36
47
|
"settings.source.config": "config/plugins.ts",
|
|
37
48
|
"settings.source.env": "environment variable",
|
|
38
49
|
"settings.key.label": "Private app token",
|
|
39
|
-
"settings.key.hint": "A key entered here overrides
|
|
50
|
+
"settings.key.hint": "A key entered here overrides config/plugins.ts and HUBSPOT_API_KEY.",
|
|
40
51
|
"settings.key.placeholder.set": "•••••••• (leave empty to keep)",
|
|
41
52
|
"settings.key.placeholder.empty": "pat-eu1-…",
|
|
53
|
+
"settings.portal.label": "Portal ID",
|
|
54
|
+
"settings.portal.hint": "HubSpot account id (Settings → Account → Account setup). Test portal today, production later.",
|
|
55
|
+
"settings.region.label": "Region",
|
|
56
|
+
"settings.region.eu1": "Europe (eu1)",
|
|
57
|
+
"settings.region.na1": "North America (na1)",
|
|
58
|
+
"settings.form.label": "Default marketing form",
|
|
59
|
+
"settings.form.hint": "Marketing form that receives submissions when a builder form doesn't pick its own. Create the form in HubSpot, then pick it here.",
|
|
60
|
+
"settings.form.placeholder": "Pick a form of the connected portal",
|
|
61
|
+
"settings.form.none": "None — CRM upsert only",
|
|
42
62
|
"settings.save": "Save",
|
|
43
63
|
"settings.test": "Test connection",
|
|
44
|
-
"settings.remove": "Remove",
|
|
64
|
+
"settings.remove": "Remove key",
|
|
45
65
|
"settings.loading": "Loading…",
|
|
46
66
|
"settings.load-error": "Could not load settings.",
|
|
47
|
-
"settings.saved": "
|
|
48
|
-
"settings.save-error": "Could not save
|
|
67
|
+
"settings.saved": "Settings saved.",
|
|
68
|
+
"settings.save-error": "Could not save settings.",
|
|
49
69
|
"settings.removed": "Key removed.",
|
|
50
70
|
"settings.remove-error": "Could not remove the key.",
|
|
51
71
|
"settings.test-ok": "Connection established — {count} readable properties.",
|
|
52
72
|
"settings.test-no-key": "No key configured.",
|
|
53
73
|
"settings.test-error": "HubSpot unreachable — invalid or revoked key?",
|
|
54
|
-
"settings.scopes": "The token needs
|
|
74
|
+
"settings.scopes": "The token needs crm.schemas.contacts.read, crm.schemas.companies.read and forms (to list, submit, and optionally update marketing forms). The token is never returned to the browser.",
|
|
55
75
|
"audit.title": "Mapping audit",
|
|
56
76
|
"audit.subtitle": "Scans every entry of the validated content types and lists the mappings the portal would reject today — including properties deleted in HubSpot since they were saved.",
|
|
57
77
|
"audit.run": "Run the audit",
|
|
@@ -111,6 +131,8 @@ const en = {
|
|
|
111
131
|
"editor.invalid": "The structure has problems — see the flagged cards.",
|
|
112
132
|
"editor.publish": "Publish",
|
|
113
133
|
"editor.published": "Form published.",
|
|
134
|
+
"editor.published-synced": "Form published. {count, plural, one {# field added} other {# fields added}} to the HubSpot form.",
|
|
135
|
+
"editor.published-sync-warn": "Form published. HubSpot field sync failed: {error}",
|
|
114
136
|
"editor.publish-blocked": "Publishing is blocked — fix the flagged mappings first.",
|
|
115
137
|
"editor.unpublish": "Unpublish",
|
|
116
138
|
"editor.unpublished": "Form unpublished.",
|
|
@@ -28,7 +28,18 @@ const fr = {
|
|
|
28
28
|
"picker.refresh": "Rafraîchir les propriétés depuis HubSpot",
|
|
29
29
|
"picker.import": "Importer les {count} options depuis HubSpot",
|
|
30
30
|
"picker.imported": "Options importées — enregistrez pour les conserver.",
|
|
31
|
-
"settings.subtitle": "
|
|
31
|
+
"settings.subtitle": "Jeton d'application privée, compte HubSpot, et la façon dont les envois atteignent le CRM. Passez du test à la prod ici — rien n'est figé dans le code.",
|
|
32
|
+
"settings.policy.title": "Comment les envois atteignent HubSpot",
|
|
33
|
+
"settings.policy.hint": "Choisissez la politique de ce portail. Les défauts restent sûrs pour toute install : conversion si un formulaire est lié, réponses en trop écrites sur le contact, formulaires HubSpot jamais mutés sauf si vous le demandez.",
|
|
34
|
+
"settings.mode.label": "Chemin d'envoi",
|
|
35
|
+
"settings.mode.hint": "Automatique utilise le formulaire marketing s'il est lié, sinon un upsert CRM. CRM seul ne compte jamais comme conversion. Formulaire marketing privilégie l'API Forms et retombe sur le CRM si HubSpot refuse l'envoi.",
|
|
36
|
+
"settings.mode.auto": "Automatique — conversion si un formulaire est lié, sinon CRM",
|
|
37
|
+
"settings.mode.forms": "Formulaire marketing — conversions HubSpot natives",
|
|
38
|
+
"settings.mode.crm": "CRM uniquement — upsert du contact, pas de conversion",
|
|
39
|
+
"settings.extra.label": "Après une conversion, écrire aussi sur le contact les champs mappés absents du formulaire HubSpot",
|
|
40
|
+
"settings.extra.hint": "L'API Forms écarte les champs inconnus (ils font échouer tout l'envoi). Activé, les champs restants atterrissent quand même sur le contact. Désactivez si HubSpot ne doit recevoir que ce que le formulaire marketing déclare.",
|
|
41
|
+
"settings.sync.label": "À la publication, ajouter au formulaire HubSpot les champs mappés manquants",
|
|
42
|
+
"settings.sync.hint": "Install Strapi-first : un champ ajouté ici apparaît sur le formulaire HubSpot à la publication suivante. Install HubSpot-first : laissez désactivé — l'import porte déjà les champs. Les propriétés CRM ne sont jamais créées ; mappez vers des propriétés déjà présentes dans le portail.",
|
|
32
43
|
"settings.configured": "Configurée {hint}",
|
|
33
44
|
"settings.not-configured": "Non configurée",
|
|
34
45
|
"settings.source": "source : {source}",
|
|
@@ -36,22 +47,31 @@ const fr = {
|
|
|
36
47
|
"settings.source.config": "config/plugins.ts",
|
|
37
48
|
"settings.source.env": "variable d'environnement",
|
|
38
49
|
"settings.key.label": "Jeton d'application privée",
|
|
39
|
-
"settings.key.hint": "Saisir une clé ici remplace
|
|
50
|
+
"settings.key.hint": "Saisir une clé ici remplace config/plugins.ts et HUBSPOT_API_KEY.",
|
|
40
51
|
"settings.key.placeholder.set": "•••••••• (laisser vide pour conserver)",
|
|
41
52
|
"settings.key.placeholder.empty": "pat-eu1-…",
|
|
53
|
+
"settings.portal.label": "ID de portail",
|
|
54
|
+
"settings.portal.hint": "Identifiant du compte HubSpot (Paramètres → Compte). Portail de test aujourd'hui, production plus tard.",
|
|
55
|
+
"settings.region.label": "Région",
|
|
56
|
+
"settings.region.eu1": "Europe (eu1)",
|
|
57
|
+
"settings.region.na1": "Amérique du Nord (na1)",
|
|
58
|
+
"settings.form.label": "Formulaire marketing par défaut",
|
|
59
|
+
"settings.form.hint": "Formulaire qui reçoit les envois quand un formulaire du builder n'en choisit pas un. Créez-le dans HubSpot, puis sélectionnez-le ici.",
|
|
60
|
+
"settings.form.placeholder": "Choisir un formulaire du portail connecté",
|
|
61
|
+
"settings.form.none": "Aucun — upsert CRM uniquement",
|
|
42
62
|
"settings.save": "Enregistrer",
|
|
43
63
|
"settings.test": "Tester la connexion",
|
|
44
|
-
"settings.remove": "Supprimer",
|
|
64
|
+
"settings.remove": "Supprimer la clé",
|
|
45
65
|
"settings.loading": "Chargement…",
|
|
46
66
|
"settings.load-error": "Réglages illisibles.",
|
|
47
|
-
"settings.saved": "
|
|
67
|
+
"settings.saved": "Réglages enregistrés.",
|
|
48
68
|
"settings.save-error": "Enregistrement impossible.",
|
|
49
69
|
"settings.removed": "Clé supprimée.",
|
|
50
70
|
"settings.remove-error": "Suppression impossible.",
|
|
51
71
|
"settings.test-ok": "Connexion établie — {count} propriétés lisibles.",
|
|
52
72
|
"settings.test-no-key": "Aucune clé configurée.",
|
|
53
73
|
"settings.test-error": "HubSpot injoignable — clé invalide ou révoquée ?",
|
|
54
|
-
"settings.scopes": "Le jeton a besoin
|
|
74
|
+
"settings.scopes": "Le jeton a besoin de crm.schemas.contacts.read, crm.schemas.companies.read et forms (lister, soumettre et éventuellement mettre à jour les formulaires marketing). Il n'est jamais renvoyé au navigateur.",
|
|
55
75
|
"audit.title": "Audit des mappings",
|
|
56
76
|
"audit.subtitle": "Parcourt toutes les entrées des content-types validés et liste les mappings que le portail refuserait aujourd'hui — y compris les propriétés supprimées dans HubSpot depuis leur enregistrement.",
|
|
57
77
|
"audit.run": "Lancer l'audit",
|
|
@@ -111,6 +131,8 @@ const fr = {
|
|
|
111
131
|
"editor.invalid": "La structure a des problèmes — voir les cartes signalées.",
|
|
112
132
|
"editor.publish": "Publier",
|
|
113
133
|
"editor.published": "Formulaire publié.",
|
|
134
|
+
"editor.published-synced": "Formulaire publié. {count, plural, one {# champ ajouté} other {# champs ajoutés}} au formulaire HubSpot.",
|
|
135
|
+
"editor.published-sync-warn": "Formulaire publié. La sync des champs HubSpot a échoué : {error}",
|
|
114
136
|
"editor.publish-blocked": "Publication bloquée — corrigez d'abord les mappings signalés.",
|
|
115
137
|
"editor.unpublish": "Dépublier",
|
|
116
138
|
"editor.unpublished": "Formulaire dépublié.",
|
|
@@ -30,7 +30,18 @@ const fr = {
|
|
|
30
30
|
"picker.refresh": "Rafraîchir les propriétés depuis HubSpot",
|
|
31
31
|
"picker.import": "Importer les {count} options depuis HubSpot",
|
|
32
32
|
"picker.imported": "Options importées — enregistrez pour les conserver.",
|
|
33
|
-
"settings.subtitle": "
|
|
33
|
+
"settings.subtitle": "Jeton d'application privée, compte HubSpot, et la façon dont les envois atteignent le CRM. Passez du test à la prod ici — rien n'est figé dans le code.",
|
|
34
|
+
"settings.policy.title": "Comment les envois atteignent HubSpot",
|
|
35
|
+
"settings.policy.hint": "Choisissez la politique de ce portail. Les défauts restent sûrs pour toute install : conversion si un formulaire est lié, réponses en trop écrites sur le contact, formulaires HubSpot jamais mutés sauf si vous le demandez.",
|
|
36
|
+
"settings.mode.label": "Chemin d'envoi",
|
|
37
|
+
"settings.mode.hint": "Automatique utilise le formulaire marketing s'il est lié, sinon un upsert CRM. CRM seul ne compte jamais comme conversion. Formulaire marketing privilégie l'API Forms et retombe sur le CRM si HubSpot refuse l'envoi.",
|
|
38
|
+
"settings.mode.auto": "Automatique — conversion si un formulaire est lié, sinon CRM",
|
|
39
|
+
"settings.mode.forms": "Formulaire marketing — conversions HubSpot natives",
|
|
40
|
+
"settings.mode.crm": "CRM uniquement — upsert du contact, pas de conversion",
|
|
41
|
+
"settings.extra.label": "Après une conversion, écrire aussi sur le contact les champs mappés absents du formulaire HubSpot",
|
|
42
|
+
"settings.extra.hint": "L'API Forms écarte les champs inconnus (ils font échouer tout l'envoi). Activé, les champs restants atterrissent quand même sur le contact. Désactivez si HubSpot ne doit recevoir que ce que le formulaire marketing déclare.",
|
|
43
|
+
"settings.sync.label": "À la publication, ajouter au formulaire HubSpot les champs mappés manquants",
|
|
44
|
+
"settings.sync.hint": "Install Strapi-first : un champ ajouté ici apparaît sur le formulaire HubSpot à la publication suivante. Install HubSpot-first : laissez désactivé — l'import porte déjà les champs. Les propriétés CRM ne sont jamais créées ; mappez vers des propriétés déjà présentes dans le portail.",
|
|
34
45
|
"settings.configured": "Configurée {hint}",
|
|
35
46
|
"settings.not-configured": "Non configurée",
|
|
36
47
|
"settings.source": "source : {source}",
|
|
@@ -38,22 +49,31 @@ const fr = {
|
|
|
38
49
|
"settings.source.config": "config/plugins.ts",
|
|
39
50
|
"settings.source.env": "variable d'environnement",
|
|
40
51
|
"settings.key.label": "Jeton d'application privée",
|
|
41
|
-
"settings.key.hint": "Saisir une clé ici remplace
|
|
52
|
+
"settings.key.hint": "Saisir une clé ici remplace config/plugins.ts et HUBSPOT_API_KEY.",
|
|
42
53
|
"settings.key.placeholder.set": "•••••••• (laisser vide pour conserver)",
|
|
43
54
|
"settings.key.placeholder.empty": "pat-eu1-…",
|
|
55
|
+
"settings.portal.label": "ID de portail",
|
|
56
|
+
"settings.portal.hint": "Identifiant du compte HubSpot (Paramètres → Compte). Portail de test aujourd'hui, production plus tard.",
|
|
57
|
+
"settings.region.label": "Région",
|
|
58
|
+
"settings.region.eu1": "Europe (eu1)",
|
|
59
|
+
"settings.region.na1": "Amérique du Nord (na1)",
|
|
60
|
+
"settings.form.label": "Formulaire marketing par défaut",
|
|
61
|
+
"settings.form.hint": "Formulaire qui reçoit les envois quand un formulaire du builder n'en choisit pas un. Créez-le dans HubSpot, puis sélectionnez-le ici.",
|
|
62
|
+
"settings.form.placeholder": "Choisir un formulaire du portail connecté",
|
|
63
|
+
"settings.form.none": "Aucun — upsert CRM uniquement",
|
|
44
64
|
"settings.save": "Enregistrer",
|
|
45
65
|
"settings.test": "Tester la connexion",
|
|
46
|
-
"settings.remove": "Supprimer",
|
|
66
|
+
"settings.remove": "Supprimer la clé",
|
|
47
67
|
"settings.loading": "Chargement…",
|
|
48
68
|
"settings.load-error": "Réglages illisibles.",
|
|
49
|
-
"settings.saved": "
|
|
69
|
+
"settings.saved": "Réglages enregistrés.",
|
|
50
70
|
"settings.save-error": "Enregistrement impossible.",
|
|
51
71
|
"settings.removed": "Clé supprimée.",
|
|
52
72
|
"settings.remove-error": "Suppression impossible.",
|
|
53
73
|
"settings.test-ok": "Connexion établie — {count} propriétés lisibles.",
|
|
54
74
|
"settings.test-no-key": "Aucune clé configurée.",
|
|
55
75
|
"settings.test-error": "HubSpot injoignable — clé invalide ou révoquée ?",
|
|
56
|
-
"settings.scopes": "Le jeton a besoin
|
|
76
|
+
"settings.scopes": "Le jeton a besoin de crm.schemas.contacts.read, crm.schemas.companies.read et forms (lister, soumettre et éventuellement mettre à jour les formulaires marketing). Il n'est jamais renvoyé au navigateur.",
|
|
57
77
|
"audit.title": "Audit des mappings",
|
|
58
78
|
"audit.subtitle": "Parcourt toutes les entrées des content-types validés et liste les mappings que le portail refuserait aujourd'hui — y compris les propriétés supprimées dans HubSpot depuis leur enregistrement.",
|
|
59
79
|
"audit.run": "Lancer l'audit",
|
|
@@ -113,6 +133,8 @@ const fr = {
|
|
|
113
133
|
"editor.invalid": "La structure a des problèmes — voir les cartes signalées.",
|
|
114
134
|
"editor.publish": "Publier",
|
|
115
135
|
"editor.published": "Formulaire publié.",
|
|
136
|
+
"editor.published-synced": "Formulaire publié. {count, plural, one {# champ ajouté} other {# champs ajoutés}} au formulaire HubSpot.",
|
|
137
|
+
"editor.published-sync-warn": "Formulaire publié. La sync des champs HubSpot a échoué : {error}",
|
|
116
138
|
"editor.publish-blocked": "Publication bloquée — corrigez d'abord les mappings signalés.",
|
|
117
139
|
"editor.unpublish": "Dépublier",
|
|
118
140
|
"editor.unpublished": "Formulaire dépublié.",
|