@saltcorn/builder 1.6.0-alpha.0 → 1.6.0-alpha.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/builder_bundle.js +4126 -2
  2. package/dist/builder_bundle.js.LICENSE.txt +18 -51
  3. package/package.json +31 -27
  4. package/src/components/Builder.js +334 -122
  5. package/src/components/Library.js +25 -13
  6. package/src/components/RenderNode.js +19 -8
  7. package/src/components/Toolbox.js +333 -269
  8. package/src/components/elements/Action.js +144 -29
  9. package/src/components/elements/Aggregation.js +20 -23
  10. package/src/components/elements/ArrayManager.js +7 -5
  11. package/src/components/elements/BoxModelEditor.js +19 -17
  12. package/src/components/elements/Card.js +47 -34
  13. package/src/components/elements/Clone.js +74 -2
  14. package/src/components/elements/Column.js +1 -1
  15. package/src/components/elements/Columns.js +27 -25
  16. package/src/components/elements/Container.js +170 -90
  17. package/src/components/elements/DropDownFilter.js +10 -8
  18. package/src/components/elements/DropMenu.js +18 -9
  19. package/src/components/elements/Field.js +9 -7
  20. package/src/components/elements/HTMLCode.js +3 -1
  21. package/src/components/elements/Image.js +20 -15
  22. package/src/components/elements/JoinField.js +15 -11
  23. package/src/components/elements/Link.js +18 -16
  24. package/src/components/elements/ListColumn.js +7 -3
  25. package/src/components/elements/ListColumns.js +4 -1
  26. package/src/components/elements/MonacoEditor.js +4 -2
  27. package/src/components/elements/Page.js +7 -4
  28. package/src/components/elements/RelationBadges.js +16 -11
  29. package/src/components/elements/RelationOnDemandPicker.js +18 -12
  30. package/src/components/elements/SearchBar.js +37 -10
  31. package/src/components/elements/Table.js +72 -65
  32. package/src/components/elements/Tabs.js +18 -15
  33. package/src/components/elements/Text.js +19 -14
  34. package/src/components/elements/ToggleFilter.js +28 -25
  35. package/src/components/elements/View.js +36 -18
  36. package/src/components/elements/ViewLink.js +15 -11
  37. package/src/components/elements/utils.js +224 -55
  38. package/src/components/storage.js +27 -129
  39. package/src/hooks/useTranslation.js +11 -0
  40. package/src/index.js +6 -3
@@ -4,8 +4,9 @@
4
4
  * @subcategory components / elements
5
5
  */
6
6
 
7
- import React, { useContext, Fragment } from "react";
7
+ import React, { Fragment, useState, useContext, useEffect } from "react";
8
8
  import { useNode } from "@craftjs/core";
9
+ import useTranslation from "../../hooks/useTranslation";
9
10
  import optionsCtx from "../context";
10
11
  import { blockProps, BlockSetting, TextStyleRow, setAPropGen } from "./utils";
11
12
  import { SingleLineEditor } from "./MonacoEditor";
@@ -49,6 +50,7 @@ export /**
49
50
  * @subcategory components
50
51
  */
51
52
  const DropDownFilterSettings = () => {
53
+ const { t } = useTranslation();
52
54
  const {
53
55
  actions: { setProp },
54
56
  name,
@@ -80,7 +82,7 @@ const DropDownFilterSettings = () => {
80
82
  <tbody>
81
83
  <tr>
82
84
  <td>
83
- <label>Field</label>
85
+ <label>{t("Field")}</label>
84
86
  </td>
85
87
  <td>
86
88
  <select
@@ -103,7 +105,7 @@ const DropDownFilterSettings = () => {
103
105
  </tr>
104
106
  <tr>
105
107
  <td>
106
- <label>Neutral label</label>
108
+ <label>{t("Neutral label")}</label>
107
109
  </td>
108
110
  <td>
109
111
  <input
@@ -115,7 +117,7 @@ const DropDownFilterSettings = () => {
115
117
  </tr>
116
118
  <tr>
117
119
  <td>
118
- <label>Where</label>
120
+ <label>{t("Where")}</label>
119
121
  </td>
120
122
  <td>
121
123
  <SingleLineEditor
@@ -127,7 +129,7 @@ const DropDownFilterSettings = () => {
127
129
  </tr>
128
130
  <tr>
129
131
  <td>
130
- <label>Label formula</label>
132
+ <label>{t("Label formula")}</label>
131
133
  </td>
132
134
  <td>
133
135
  <input
@@ -157,7 +159,7 @@ const DropDownFilterSettings = () => {
157
159
  checked={full_width}
158
160
  onChange={setAProp("full_width", { checked: true })}
159
161
  />
160
- <label className="form-check-label">Full width</label>
162
+ <label className="form-check-label">{t("Full width")}</label>
161
163
  </div>
162
164
  </td>
163
165
  </tr>
@@ -173,7 +175,7 @@ const DropDownFilterSettings = () => {
173
175
  checked={all_options}
174
176
  onChange={setAProp("all_options", { checked: true })}
175
177
  />
176
- <label className="form-check-label">All options</label>
178
+ <label className="form-check-label">{t("All options")}</label>
177
179
  </div>
178
180
  </td>
179
181
  </tr>
@@ -190,7 +192,7 @@ const DropDownFilterSettings = () => {
190
192
  checked={apply_select2}
191
193
  onChange={setAProp("apply_select2", { checked: true })}
192
194
  />
193
- <label className="form-check-label">Apply select2</label>
195
+ <label className="form-check-label">{t("Apply select2")}</label>
194
196
  </div>
195
197
  </td>
196
198
  </tr>
@@ -4,7 +4,8 @@
4
4
  * @subcategory components / elements
5
5
  */
6
6
 
7
- import React, { Fragment, useState, useContext } from "react";
7
+ import React, { Fragment, useState, useContext, useEffect } from "react";
8
+ import useTranslation from "../../hooks/useTranslation";
8
9
  import optionsCtx from "../context";
9
10
  import { Element, useNode } from "@craftjs/core";
10
11
  import { Column } from "./Column";
@@ -32,7 +33,7 @@ export /**
32
33
  * @subcategory components
33
34
  */
34
35
  const DropMenu = ({
35
- children,
36
+ contents,
36
37
  action_style,
37
38
  action_size,
38
39
  action_icon,
@@ -43,12 +44,12 @@ const DropMenu = ({
43
44
  label,
44
45
  menu_direction,
45
46
  }) => {
47
+ const { t } = useTranslation();
46
48
  const {
47
49
  selected,
48
50
  connectors: { connect, drag },
49
51
  } = useNode((node) => ({ selected: node.events.selected }));
50
52
  const [showDropdown, setDropdown] = useState(false);
51
- //const [dropWidth, setDropWidth] = useState(200);
52
53
  return (
53
54
  <div
54
55
  className={`${selected ? "selected-node" : ""} ${block ? "d-block" : "d-inline"}`}
@@ -80,7 +81,9 @@ const DropMenu = ({
80
81
  showDropdown ? "show" : ""
81
82
  } ${menu_direction === "end" ? "dropdown-menu-end" : ""}`}
82
83
  >
83
- <div className="canvas d-flex flex-column">{children}</div>
84
+ <Element canvas id="dropmenu-contents" is={Column}>
85
+ {contents}
86
+ </Element>
84
87
  </div>
85
88
  </div>
86
89
  );
@@ -93,6 +96,7 @@ export /**
93
96
  * @subcategory components
94
97
  */
95
98
  const DropMenuSettings = () => {
99
+ const { t } = useTranslation();
96
100
  const node = useNode((node) => ({
97
101
  label: node.data.props.label,
98
102
  block: node.data.props.block,
@@ -117,7 +121,7 @@ const DropMenuSettings = () => {
117
121
  <tbody>
118
122
  <SettingsRow
119
123
  field={{
120
- label: "Label",
124
+ label: t("Label"),
121
125
  name: "label",
122
126
  type: "String",
123
127
  }}
@@ -138,18 +142,18 @@ const DropMenuSettings = () => {
138
142
  </tr>
139
143
  <SettingsRow
140
144
  field={{
141
- label: "Drop direction",
145
+ label: t("Drop direction"),
142
146
  name: "menu_direction",
143
147
  type: "btn_select",
144
148
  options: [
145
149
  {
146
150
  value: "end",
147
- title: "End",
151
+ title: t("End"),
148
152
  label: <FontAwesomeIcon icon={faCaretSquareLeft} />,
149
153
  },
150
154
  {
151
155
  value: "start",
152
- title: "Start",
156
+ title: t("Start"),
153
157
  label: <FontAwesomeIcon icon={faCaretSquareRight} />,
154
158
  },
155
159
  ],
@@ -174,8 +178,13 @@ DropMenu.craft = {
174
178
  related: {
175
179
  settings: DropMenuSettings,
176
180
  segment_type: "dropdown_menu",
177
- hasContents: true,
178
181
  fields: [
182
+ {
183
+ label: "Contents",
184
+ name: "contents",
185
+ type: "Nodes",
186
+ nodeID: "dropmenu-contents",
187
+ },
179
188
  "label",
180
189
  "block",
181
190
  "action_style",
@@ -8,6 +8,7 @@ import React, { useContext, useEffect, useState, Fragment } from "react";
8
8
  import { useNode } from "@craftjs/core";
9
9
  import optionsCtx from "../context";
10
10
  import previewCtx from "../preview_context";
11
+ import useTranslation from "../../hooks/useTranslation";
11
12
  import {
12
13
  blockProps,
13
14
  BlockOrInlineSetting,
@@ -87,6 +88,7 @@ export /**
87
88
  * @subcategory components
88
89
  */
89
90
  const FieldSettings = () => {
91
+ const { t } = useTranslation();
90
92
  const {
91
93
  actions: { setProp },
92
94
  name,
@@ -153,14 +155,14 @@ const FieldSettings = () => {
153
155
  <Fragment>
154
156
  <i>
155
157
  <small>
156
- Previews shown in canvas are indicative based on random rows
158
+ {t("Previews shown in canvas are indicative based on random rows")}
157
159
  </small>
158
160
  </i>
159
161
  <table className="w-100">
160
162
  <tbody>
161
163
  <tr>
162
164
  <td>
163
- <label>Field</label>
165
+ <label>{t("Field")}</label>
164
166
  </td>
165
167
  <td>
166
168
  <select
@@ -192,7 +194,7 @@ const FieldSettings = () => {
192
194
  <tr>
193
195
  <td>
194
196
  <label>
195
- Field view
197
+ {t("Field view")}
196
198
  <HelpTopicLink
197
199
  topic="Field views"
198
200
  field_name={name}
@@ -241,7 +243,7 @@ const FieldSettings = () => {
241
243
  }
242
244
  }}
243
245
  />
244
- <label className="form-check-label">Click to edit?</label>
246
+ <label className="form-check-label">{t("Click to edit?")}</label>
245
247
  </div>
246
248
  </td>
247
249
  </tr>
@@ -277,7 +279,7 @@ const FieldSettings = () => {
277
279
  ) : null}
278
280
  {options.mode === "edit" && options.triggerActions ? (
279
281
  <Fragment>
280
- <label>On change action</label>
282
+ <label>{t("On change action")}</label>
281
283
  <select
282
284
  value={onchange_action}
283
285
  className="on-change-action form-control form-select"
@@ -289,7 +291,7 @@ const FieldSettings = () => {
289
291
  });
290
292
  }}
291
293
  >
292
- <option value="">None</option>
294
+ <option value="">{t("None")}</option>
293
295
  {options.triggerActions.map((f, ix) => (
294
296
  <option key={ix} value={f}>
295
297
  {f}
@@ -302,7 +304,7 @@ const FieldSettings = () => {
302
304
  target="_blank"
303
305
  href={`/actions/configure/${onchange_action}`}
304
306
  >
305
- Configure this action
307
+ {t("Configure this action")}
306
308
  </a>
307
309
  ) : null}
308
310
  </Fragment>
@@ -5,6 +5,7 @@
5
5
  */
6
6
 
7
7
  import React, { Fragment, useContext } from "react";
8
+ import useTranslation from "../../hooks/useTranslation";
8
9
  import { useNode } from "@craftjs/core";
9
10
  import {
10
11
  blockProps,
@@ -27,12 +28,13 @@ const HTMLCode = ({ text }) => {
27
28
  selected,
28
29
  connectors: { connect, drag },
29
30
  } = useNode((node) => ({ selected: node.events.selected }));
31
+ const { t } = useTranslation();
30
32
  return (
31
33
  <span
32
34
  className={`is-html-block ${selected ? "selected-node" : ""}`}
33
35
  ref={(dom) => connect(drag(dom))}
34
36
  >
35
- <div style={{ fontSize: "8px" }}>HTML</div>
37
+ <div style={{ fontSize: "8px" }}>{t("HTML")}</div>
36
38
  <div dangerouslySetInnerHTML={{ __html: text }}></div>
37
39
  </span>
38
40
  );
@@ -8,6 +8,7 @@ import React, { useContext, Fragment } from "react";
8
8
  import { useNode } from "@craftjs/core";
9
9
  import optionsCtx from "../context";
10
10
  import previewCtx from "../preview_context";
11
+ import useTranslation from "../../hooks/useTranslation";
11
12
  import { BoxModelEditor } from "./BoxModelEditor";
12
13
 
13
14
  import {
@@ -38,6 +39,7 @@ const Image = ({ fileid, block, srctype, url, alt, style, customClass }) => {
38
39
  selected,
39
40
  connectors: { connect, drag },
40
41
  } = useNode((node) => ({ selected: node.events.selected }));
42
+ const { t } = useTranslation();
41
43
  const theurl =
42
44
  srctype === "File"
43
45
  ? /^(?:[a-z]+:)?\/\//i.test(fileid)
@@ -53,7 +55,7 @@ const Image = ({ fileid, block, srctype, url, alt, style, customClass }) => {
53
55
  ref={(dom) => connect(drag(dom))}
54
56
  style={reactifyStyles(style || {})}
55
57
  >
56
- No images Available
58
+ {t("No images Available")}
57
59
  </span>
58
60
  ) : (
59
61
  <img
@@ -76,6 +78,7 @@ export /**
76
78
  * @subcategory components
77
79
  */
78
80
  const ImageSettings = () => {
81
+ const { t } = useTranslation();
79
82
  const node = useNode((node) => ({
80
83
  fileid: node.data.props.fileid,
81
84
  field: node.data.props.field,
@@ -147,23 +150,23 @@ const ImageSettings = () => {
147
150
  value={currentSettingsTab}
148
151
  onChange={(ix) => setProp((prop) => (prop.currentSettingsTab = ix))}
149
152
  >
150
- <table accordiontitle="Select image">
153
+ <table accordiontitle={t("Select image")}>
151
154
  <tbody>
152
155
  <tr>
153
156
  <td colSpan="2">
154
157
  <i>
155
- <small>Preview shown in canvas is indicative</small>
158
+ <small>{t("Preview shown in canvas is indicative")}</small>
156
159
  </i>
157
160
  </td>
158
161
  </tr>
159
162
  <tr>
160
163
  <td>
161
- <label>Source</label>
164
+ <label>{t("Source")}</label>
162
165
  </td>
163
166
  <td>
164
167
  <select
165
168
  value={srctype}
166
- className="form-control form-select"
169
+ className="form-control form-select"
167
170
  onChange={setAProp("srctype")}
168
171
  >
169
172
  {buildOptions(sourceOpts)}
@@ -173,7 +176,7 @@ const ImageSettings = () => {
173
176
  {srctype === "File" && (
174
177
  <tr>
175
178
  <td>
176
- <label>File</label>
179
+ <label>{t("File")}</label>
177
180
  </td>
178
181
  <td>
179
182
  <select
@@ -199,7 +202,7 @@ const ImageSettings = () => {
199
202
  {srctype === "URL" && (
200
203
  <tr>
201
204
  <td>
202
- <label>URL</label>
205
+ <label>{t("URL")}</label>
203
206
  </td>
204
207
  <td>
205
208
  <OrFormula nodekey="url" {...{ setProp, isFormula, node }}>
@@ -217,7 +220,7 @@ const ImageSettings = () => {
217
220
  {srctype === "Upload" && (
218
221
  <tr>
219
222
  <td>
220
- <label>File</label>
223
+ <label>{t("File")}</label>
221
224
  </td>
222
225
  <td>
223
226
  <input
@@ -232,7 +235,7 @@ const ImageSettings = () => {
232
235
  {srctype === "Field" && (
233
236
  <tr>
234
237
  <td>
235
- <label>Field</label>
238
+ <label>{t("Field")}</label>
236
239
  </td>
237
240
  <td>
238
241
  <select
@@ -260,7 +263,7 @@ const ImageSettings = () => {
260
263
  {srctype !== "Upload" && (
261
264
  <tr>
262
265
  <td>
263
- <label>Alt text</label>
266
+ <label>{t("Alt text")}</label>
264
267
  </td>
265
268
  <td>
266
269
  <OrFormula nodekey="alt" {...{ setProp, isFormula, node }}>
@@ -277,7 +280,7 @@ const ImageSettings = () => {
277
280
  {srctype !== "Upload" && (
278
281
  <tr>
279
282
  <td style={{ verticalAlign: "top" }}>
280
- <label>Responsive widths</label>
283
+ <label>{t("Responsive widths")}</label>
281
284
  </td>
282
285
 
283
286
  <td>
@@ -290,7 +293,9 @@ const ImageSettings = () => {
290
293
  />
291
294
  <small>
292
295
  <i>
293
- List of widths to serve resized images, e.g. 300, 400, 600
296
+ {t(
297
+ "List of widths to serve resized images, e.g. 300, 400, 600"
298
+ )}
294
299
  </i>
295
300
  </small>
296
301
  </td>
@@ -299,7 +304,7 @@ const ImageSettings = () => {
299
304
  <SettingsRow
300
305
  field={{
301
306
  name: "object-fit",
302
- label: "Object fit",
307
+ label: t("Object fit"),
303
308
  type: "select",
304
309
  options: ["none", "fill", "contain", "cover", "scale-down"],
305
310
  }}
@@ -308,7 +313,7 @@ const ImageSettings = () => {
308
313
  isStyle={true}
309
314
  />
310
315
  <tr>
311
- <td>Class</td>
316
+ <td>{t("Class")}</td>
312
317
  <td>
313
318
  <input
314
319
  type="text"
@@ -328,7 +333,7 @@ const ImageSettings = () => {
328
333
  )}
329
334
  </tbody>
330
335
  </table>
331
- <div accordiontitle="Box" className="w-100">
336
+ <div accordiontitle={t("Box")} className="w-100">
332
337
  <BoxModelEditor setProp={setProp} node={node} sizeWithStyle={true} />
333
338
  </div>
334
339
  </Accordion>
@@ -5,7 +5,8 @@
5
5
  */
6
6
  /* eslint-env jquery */
7
7
 
8
- import React, { useContext, useEffect, useState, Fragment } from "react";
8
+ import React, { Fragment, useState, useContext, useEffect } from "react";
9
+ import useTranslation from "../../hooks/useTranslation";
9
10
  import { useNode } from "@craftjs/core";
10
11
  import optionsCtx from "../context";
11
12
  import {
@@ -66,7 +67,7 @@ const JoinField = ({ name, block, fieldview, textStyle }) => {
66
67
  );
67
68
  };
68
69
 
69
- const buildFieldsMenu = (options, setProp, refetchPreview) => {
70
+ const buildFieldsMenu = (options, setProp, refetchPreview, t) => {
70
71
  const { join_field_options } = options.join_field_picker_data;
71
72
  return (
72
73
  <div className="dropdown">
@@ -81,7 +82,7 @@ const buildFieldsMenu = (options, setProp, refetchPreview) => {
81
82
  className="btn btn-outline-primary dropdown-toggle"
82
83
  aria-expanded="false"
83
84
  >
84
- Fields
85
+ {t("Fields")}
85
86
  </button>
86
87
  <div className="dropdown-menu">
87
88
  <ul className="ps-0 mb-0">
@@ -249,7 +250,8 @@ const buildRelationsMenu = (
249
250
  options,
250
251
  setProp,
251
252
  refetchPreview,
252
- hasFieldsPicker
253
+ hasFieldsPicker,
254
+ t
253
255
  ) => {
254
256
  const { relation_options } = options.join_field_picker_data;
255
257
  return (
@@ -265,7 +267,7 @@ const buildRelationsMenu = (
265
267
  className="btn btn-outline-primary dropdown-toggle"
266
268
  aria-expanded="false"
267
269
  >
268
- Relations
270
+ {t("Relations")}
269
271
  </button>
270
272
  <div className="dropdown-menu">
271
273
  <ul className="ps-0 mb-0">
@@ -369,6 +371,7 @@ export /**
369
371
  * @subcategory components
370
372
  */
371
373
  const JoinFieldSettings = () => {
374
+ const { t } = useTranslation();
372
375
  const {
373
376
  actions: { setProp },
374
377
  name,
@@ -432,14 +435,14 @@ const JoinFieldSettings = () => {
432
435
  <Fragment>
433
436
  <i>
434
437
  <small>
435
- Previews shown in canvas are indicative based on random rows
438
+ {t("Previews shown in canvas are indicative based on random rows")}
436
439
  </small>
437
440
  </i>
438
441
  <table className="w-100">
439
442
  <tbody>
440
443
  <tr>
441
444
  <td>
442
- <label>Join field</label>
445
+ <label>{t("Join field")}</label>
443
446
  </td>
444
447
  <td>
445
448
  <input
@@ -459,13 +462,14 @@ const JoinFieldSettings = () => {
459
462
  <td colSpan="2">
460
463
  <div className="d-flex">
461
464
  {showFieldsPicker &&
462
- buildFieldsMenu(options, setProp, refetchPreview)}
465
+ buildFieldsMenu(options, setProp, refetchPreview, t)}
463
466
  {showRelationsPicker &&
464
467
  buildRelationsMenu(
465
468
  options,
466
469
  setProp,
467
470
  refetchPreview,
468
- showFieldsPicker
471
+ showFieldsPicker,
472
+ t
469
473
  )}
470
474
  </div>
471
475
  </td>
@@ -473,7 +477,7 @@ const JoinFieldSettings = () => {
473
477
  {fvs && (
474
478
  <tr>
475
479
  <td>
476
- <label>Field view</label>
480
+ <label>{t("Field view")}</label>
477
481
  </td>
478
482
 
479
483
  <td>
@@ -513,7 +517,7 @@ const JoinFieldSettings = () => {
513
517
  }
514
518
  }}
515
519
  />
516
- <label className="form-check-label">Click to edit?</label>
520
+ <label className="form-check-label">{t("Click to edit?")}</label>
517
521
  </div>
518
522
  </td>
519
523
  </tr>
@@ -6,6 +6,7 @@
6
6
 
7
7
  import React, { Fragment, useContext } from "react";
8
8
  import { useNode } from "@craftjs/core";
9
+ import useTranslation from "../../hooks/useTranslation";
9
10
  import {
10
11
  blockProps,
11
12
  BlockSetting,
@@ -94,6 +95,7 @@ export /**
94
95
  * @subcategory components
95
96
  */
96
97
  const LinkSettings = () => {
98
+ const { t } = useTranslation();
97
99
  const node = useNode((node) => ({
98
100
  text: node.data.props.text,
99
101
  url: node.data.props.url,
@@ -137,7 +139,7 @@ const LinkSettings = () => {
137
139
  <tbody>
138
140
  <tr>
139
141
  <td>
140
- <label>Text to display</label>
142
+ <label>{t("Text to display")}</label>
141
143
  </td>
142
144
  <td>
143
145
  <OrFormula nodekey="text" {...{ setProp, isFormula, node }}>
@@ -152,7 +154,7 @@ const LinkSettings = () => {
152
154
  </tr>
153
155
  <tr>
154
156
  <td>
155
- <label>Link source</label>
157
+ <label>{t("Link source")}</label>
156
158
  </td>
157
159
  <td>
158
160
  <select
@@ -169,14 +171,14 @@ const LinkSettings = () => {
169
171
  });
170
172
  }}
171
173
  >
172
- <option>URL</option>
173
- {(options.pages || []).length > 0 && <option>Page</option>}
174
+ <option>{t("URL")}</option>
175
+ {(options.pages || []).length > 0 && <option>{t("Page")}</option>}
174
176
  {(options.views || []).length > 0 &&
175
177
  ["page", "filter"].includes(options.mode) && (
176
- <option>View</option>
178
+ <option>{t("View")}</option>
177
179
  )}
178
180
  {(options.page_groups || []).length > 0 && (
179
- <option>Page Group</option>
181
+ <option>{t("Page Group")}</option>
180
182
  )}
181
183
  </select>
182
184
  </td>
@@ -184,7 +186,7 @@ const LinkSettings = () => {
184
186
  {link_src === "URL" && (
185
187
  <tr>
186
188
  <td>
187
- <label>URL</label>
189
+ <label>{t("URL")}</label>
188
190
  </td>
189
191
  <td>
190
192
  <OrFormula nodekey="url" {...{ setProp, isFormula, node }}>
@@ -202,7 +204,7 @@ const LinkSettings = () => {
202
204
  {link_src === "Page" && (
203
205
  <tr>
204
206
  <td>
205
- <label>Page</label>
207
+ <label>{t("Page")}</label>
206
208
  </td>
207
209
  <td>
208
210
  <select
@@ -223,7 +225,7 @@ const LinkSettings = () => {
223
225
  {link_src === "Page Group" && (
224
226
  <tr>
225
227
  <td>
226
- <label>Page Group</label>
228
+ <label>{t("Page Group")}</label>
227
229
  </td>
228
230
  <td>
229
231
  <select
@@ -244,7 +246,7 @@ const LinkSettings = () => {
244
246
  {link_src === "View" && (
245
247
  <tr>
246
248
  <td>
247
- <label>View</label>
249
+ <label>{t("View")}</label>
248
250
  </td>
249
251
  <td>
250
252
  <select
@@ -265,7 +267,7 @@ const LinkSettings = () => {
265
267
  {link_src === "View" && (
266
268
  <tr>
267
269
  <td>
268
- <label>State Formula</label>
270
+ <label>{t("State Formula")}</label>
269
271
  </td>
270
272
  <td>
271
273
  <input
@@ -299,7 +301,7 @@ const LinkSettings = () => {
299
301
  checked={nofollow}
300
302
  onChange={setAProp("nofollow", { checked: true })}
301
303
  />
302
- <label className="form-check-label">Nofollow</label>
304
+ <label className="form-check-label">{t("Nofollow")}</label>
303
305
  </div>
304
306
  <div className="form-check">
305
307
  <input
@@ -309,7 +311,7 @@ const LinkSettings = () => {
309
311
  checked={target_blank}
310
312
  onChange={setAProp("target_blank", { checked: true })}
311
313
  />
312
- <label className="form-check-label">Open in new tab</label>
314
+ <label className="form-check-label">{t("Open in new tab")}</label>
313
315
  </div>
314
316
  <div className="form-check">
315
317
  <input
@@ -319,7 +321,7 @@ const LinkSettings = () => {
319
321
  checked={in_modal}
320
322
  onChange={setAProp("in_modal", { checked: true })}
321
323
  />
322
- <label className="form-check-label">Open in popup modal?</label>
324
+ <label className="form-check-label">{t("Open in popup modal?")}</label>
323
325
  </div>
324
326
 
325
327
  {["filter", "page"].includes(options.mode) && (
@@ -331,7 +333,7 @@ const LinkSettings = () => {
331
333
  checked={transfer_state}
332
334
  onChange={setAProp("transfer_state", { checked: true })}
333
335
  />
334
- <label className="form-check-label">Transfer state</label>
336
+ <label className="form-check-label">{t("Transfer state")}</label>
335
337
  </div>
336
338
  )}
337
339
 
@@ -354,7 +356,7 @@ const LinkSettings = () => {
354
356
  : ""
355
357
  }
356
358
  >
357
- Configure this {link_src}
359
+ {t("Configure this")} {link_src}
358
360
  </a>
359
361
  </td>
360
362
  </tr>