@fonderie/react-courier-admin-screens 0.7.0 → 0.8.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/index.cjs CHANGED
@@ -27,6 +27,7 @@ __export(index_exports, {
27
27
  module.exports = __toCommonJS(index_exports);
28
28
 
29
29
  // src/screens/TemplateEditorScreen.tsx
30
+ var import_client = require("@fonderie/client");
30
31
  var import_react_courier_admin = require("@fonderie/react-courier-admin");
31
32
  var import_react = require("react");
32
33
  var import_jsx_runtime = require("react/jsx-runtime");
@@ -39,8 +40,10 @@ function TemplateEditorScreen({
39
40
  onSaved,
40
41
  system = false,
41
42
  onDeleted,
42
- onAddLocale
43
+ onAddLocale,
44
+ uiLocale
43
45
  }) {
46
+ const t = (0, import_react.useMemo)(() => (0, import_client.createAdminT)(uiLocale), [uiLocale]);
44
47
  const { template, isLoading, error, refresh } = (0, import_react_courier_admin.useTemplate)(client, type, locale);
45
48
  const { saveTemplate, removeTemplate } = (0, import_react_courier_admin.useTemplates)(client);
46
49
  const [isDeleting, setIsDeleting] = (0, import_react.useState)(false);
@@ -66,13 +69,13 @@ function TemplateEditorScreen({
66
69
  try {
67
70
  const parsed = JSON.parse(sampleJson || "{}");
68
71
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
69
- setSampleError("Sample data must be a JSON object.");
72
+ setSampleError(t("templates.editor.sampleNotObject"));
70
73
  return;
71
74
  }
72
75
  data = parsed;
73
76
  setSampleError(null);
74
77
  } catch {
75
- setSampleError("Sample data is not valid JSON.");
78
+ setSampleError(t("templates.editor.sampleInvalid"));
76
79
  return;
77
80
  }
78
81
  const result = await renderPreview(
@@ -85,7 +88,7 @@ function TemplateEditorScreen({
85
88
  const seeded = { ...data, ...Object.fromEntries(missing.map((v) => [v, v])) };
86
89
  setSampleJson(JSON.stringify(seeded, null, 2));
87
90
  }
88
- }, [renderPreview, type, text, subject, html, locale, sampleJson]);
91
+ }, [renderPreview, type, text, subject, html, locale, sampleJson, t]);
89
92
  const runRef = (0, import_react.useRef)(run);
90
93
  runRef.current = run;
91
94
  const loadedType = template ? `${type}:${locale ?? ""}` : null;
@@ -114,9 +117,8 @@ function TemplateEditorScreen({
114
117
  }
115
118
  };
116
119
  const handleDelete = async () => {
117
- const which = locale ? `the ${locale} version of "${type}"` : `"${type}"`;
118
- const fallback = locale ? " People in that locale will receive the default version." : "";
119
- if (!window.confirm(`Delete ${which}?${fallback}`)) return;
120
+ const message = locale ? t("templates.editor.confirmDeleteLocale", { type, locale }) : t("templates.editor.confirmDelete", { type });
121
+ if (!window.confirm(message)) return;
120
122
  setIsDeleting(true);
121
123
  setSaveError(null);
122
124
  try {
@@ -128,7 +130,7 @@ function TemplateEditorScreen({
128
130
  setIsDeleting(false);
129
131
  }
130
132
  };
131
- if (isLoading) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.status, children: "Loading template\u2026" });
133
+ if (isLoading) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.status, children: t("templates.editor.loading") });
132
134
  if (error)
133
135
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.error, role: "alert", children: error.explanation });
134
136
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.container, children: [
@@ -140,20 +142,20 @@ function TemplateEditorScreen({
140
142
  type: "button",
141
143
  style: { ...styles.rollbackButton, marginLeft: "auto" },
142
144
  onClick: () => onAddLocale(type),
143
- children: "+ Add locale"
145
+ children: t("templates.editor.addLocale")
144
146
  }
145
147
  ) : null
146
148
  ] }),
147
149
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.meta, children: [
148
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: locale ?? "default locale" }),
150
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: locale ?? t("templates.defaultLocale") }),
149
151
  " \xB7 v",
150
152
  template?.version ?? 1,
151
- system ? " \xB7 built-in email: edit or roll back, it cannot be deleted" : ""
153
+ system ? ` \xB7 ${t("templates.editor.builtInNote")}` : ""
152
154
  ] }),
153
155
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.split, children: [
154
156
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.column, children: [
155
157
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { style: styles.form, onSubmit: handleSubmit, children: [
156
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { style: styles.label, htmlFor: "template-subject", children: "Subject" }),
158
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { style: styles.label, htmlFor: "template-subject", children: t("templates.subject") }),
157
159
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
158
160
  "input",
159
161
  {
@@ -163,7 +165,7 @@ function TemplateEditorScreen({
163
165
  onChange: (event) => setSubject(event.target.value)
164
166
  }
165
167
  ),
166
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { style: styles.label, htmlFor: "template-html", children: "HTML body" }),
168
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { style: styles.label, htmlFor: "template-html", children: t("templates.htmlBody") }),
167
169
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
168
170
  "textarea",
169
171
  {
@@ -174,7 +176,7 @@ function TemplateEditorScreen({
174
176
  rows: 8
175
177
  }
176
178
  ),
177
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { style: styles.label, htmlFor: "template-text", children: "Plain-text body" }),
179
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { style: styles.label, htmlFor: "template-text", children: t("templates.textBody") }),
178
180
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
179
181
  "textarea",
180
182
  {
@@ -195,10 +197,10 @@ function TemplateEditorScreen({
195
197
  onChange: (event) => setActive(event.target.checked)
196
198
  }
197
199
  ),
198
- "Active"
200
+ t("templates.editor.active")
199
201
  ] }),
200
202
  saveError?.reason === "VERSION_CONFLICT" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.error, role: "alert", children: [
201
- "Someone changed this template since you opened it. Reload to see their change, then edit again.",
203
+ t("templates.editor.conflict"),
202
204
  " ",
203
205
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
204
206
  "button",
@@ -209,7 +211,7 @@ function TemplateEditorScreen({
209
211
  setSaveError(null);
210
212
  void refresh();
211
213
  },
212
- children: "Reload"
214
+ children: t("common.reload")
213
215
  }
214
216
  )
215
217
  ] }) : saveError ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.error, role: "alert", children: saveError.explanation }) : null,
@@ -220,10 +222,10 @@ function TemplateEditorScreen({
220
222
  type: "submit",
221
223
  disabled: isSaving || !dirty,
222
224
  style: dirty ? styles.button : styles.buttonDisabled,
223
- children: isSaving ? "Saving\u2026" : "Save"
225
+ children: isSaving ? t("common.saving") : t("common.save")
224
226
  }
225
227
  ),
226
- !dirty && !isSaving && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.meta, children: "No changes to save" }),
228
+ !dirty && !isSaving && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.meta, children: t("templates.editor.noChanges") }),
227
229
  !system ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
228
230
  "button",
229
231
  {
@@ -237,12 +239,12 @@ function TemplateEditorScreen({
237
239
  color: "var(--fonderie-danger,#e00)",
238
240
  borderColor: "color-mix(in srgb, var(--fonderie-danger,#e00) 40%, transparent)"
239
241
  },
240
- children: isDeleting ? "Deleting\u2026" : "Delete"
242
+ children: isDeleting ? t("common.deleting") : t("common.delete")
241
243
  }
242
244
  ) : null
243
245
  ] })
244
246
  ] }),
245
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { style: styles.label, htmlFor: "template-sample", children: "Sample data" }),
247
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { style: styles.label, htmlFor: "template-sample", children: t("templates.editor.sampleData") }),
246
248
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
247
249
  "textarea",
248
250
  {
@@ -258,8 +260,8 @@ function TemplateEditorScreen({
258
260
  ] }),
259
261
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.previewColumn, children: [
260
262
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.previewHeader, children: [
261
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.label, children: "Preview" }),
262
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.meta, children: isPreviewing ? "Rendering\u2026" : "Live" })
263
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.label, children: t("templates.editor.preview") }),
264
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.meta, children: isPreviewing ? t("templates.editor.rendering") : t("templates.editor.live") })
263
265
  ] }),
264
266
  previewError && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.error, role: "alert", children: previewError.explanation }),
265
267
  preview?.subject && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.previewSubject, children: preview.subject }),
@@ -270,26 +272,26 @@ function TemplateEditorScreen({
270
272
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
271
273
  "iframe",
272
274
  {
273
- title: "Template preview",
275
+ title: t("templates.editor.previewTitle"),
274
276
  style: styles.previewFrame,
275
277
  sandbox: "",
276
278
  srcDoc: preview.html
277
279
  }
278
280
  )
279
- ) : preview ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("pre", { style: styles.previewText, children: preview.text }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.meta, children: "Nothing rendered yet." })
281
+ ) : preview ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("pre", { style: styles.previewText, children: preview.text }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.meta, children: t("templates.editor.nothingRendered") })
280
282
  ] })
281
283
  ] }),
282
284
  revisions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.revisions, children: [
283
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { style: styles.subtitle, children: "History" }),
285
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { style: styles.subtitle, children: t("templates.editor.history") }),
284
286
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { style: styles.list, children: revisions.map((rev) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { style: styles.row, children: [
285
287
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
286
288
  "v",
287
289
  rev.version,
288
290
  " \u2014 ",
289
- rev.actor ?? "unknown",
291
+ rev.actor ?? t("templates.editor.unknownActor"),
290
292
  " \u2014",
291
293
  " ",
292
- new Date(rev.createdAt).toLocaleString()
294
+ (0, import_client.formatAdminDate)(rev.createdAt, uiLocale)
293
295
  ] }),
294
296
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
295
297
  "button",
@@ -297,7 +299,7 @@ function TemplateEditorScreen({
297
299
  type: "button",
298
300
  onClick: () => rollback(rev.version),
299
301
  style: styles.rollbackButton,
300
- children: "Roll back"
302
+ children: t("templates.editor.rollBack")
301
303
  }
302
304
  )
303
305
  ] }, rev.version)) })
@@ -473,13 +475,16 @@ var styles = {
473
475
  };
474
476
 
475
477
  // src/screens/TemplateListScreen.tsx
478
+ var import_client2 = require("@fonderie/client");
476
479
  var import_react_courier_admin2 = require("@fonderie/react-courier-admin");
477
480
  var import_jsx_runtime2 = require("react/jsx-runtime");
478
481
  function TemplateListScreen({
479
482
  client,
480
483
  onSelectTemplate,
481
- onCreateTemplate
484
+ onCreateTemplate,
485
+ locale
482
486
  }) {
487
+ const t = (0, import_client2.createAdminT)(locale);
483
488
  const { templates, isLoading, error } = (0, import_react_courier_admin2.useTemplates)(client);
484
489
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles2.container, children: [
485
490
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
@@ -487,25 +492,25 @@ function TemplateListScreen({
487
492
  {
488
493
  style: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 16 },
489
494
  children: [
490
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h1", { style: styles2.title, children: "Templates" }),
495
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h1", { style: styles2.title, children: t("templates.list.title") }),
491
496
  onCreateTemplate ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
492
497
  "button",
493
498
  {
494
499
  type: "button",
495
500
  onClick: () => onCreateTemplate({
496
501
  locales: [
497
- ...new Set(templates.map((t) => t.locale).filter((l) => !!l))
502
+ ...new Set(templates.map((row) => row.locale).filter((l) => !!l))
498
503
  ]
499
504
  }),
500
505
  style: styles2.newButton,
501
- children: "New template"
506
+ children: t("templates.list.newTemplate")
502
507
  }
503
508
  ) : null
504
509
  ]
505
510
  }
506
511
  ),
507
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: styles2.hint, children: "Every email the app sends. Open one to edit its copy and preview it live." }),
508
- isLoading ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: styles2.status, children: "Loading templates\u2026" }) : error ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: styles2.error, role: "alert", children: error.explanation }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("ul", { style: styles2.list, children: templates.map((template) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("li", { style: styles2.row, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
512
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: styles2.hint, children: t("templates.list.hint") }),
513
+ isLoading ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: styles2.status, children: t("templates.list.loading") }) : error ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: styles2.error, role: "alert", children: error.explanation }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("ul", { style: styles2.list, children: templates.map((template) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("li", { style: styles2.row, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
509
514
  "button",
510
515
  {
511
516
  type: "button",
@@ -513,11 +518,11 @@ function TemplateListScreen({
513
518
  style: styles2.rowButton,
514
519
  children: [
515
520
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: styles2.type, children: template.type }),
516
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: styles2.locale, children: template.locale ?? "default locale" }),
517
- template.system ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: styles2.builtIn, children: "built-in" }) : null,
521
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: styles2.locale, children: template.locale ?? t("templates.defaultLocale") }),
522
+ template.system ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: styles2.builtIn, children: t("templates.builtInBadge") }) : null,
518
523
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: template.active ? styles2.active : styles2.inactive, children: [
519
524
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: styles2.dot }),
520
- template.active ? "active" : "inactive"
525
+ template.active ? t("common.status.active") : t("common.status.inactive")
521
526
  ] })
522
527
  ]
523
528
  }
@@ -616,7 +621,7 @@ var styles2 = {
616
621
  };
617
622
 
618
623
  // src/screens/TemplateCreateScreen.tsx
619
- var import_client = require("@fonderie/client");
624
+ var import_client3 = require("@fonderie/client");
620
625
  var import_react2 = require("react");
621
626
  var import_jsx_runtime3 = require("react/jsx-runtime");
622
627
  var TYPE_RE = /^[a-z0-9][a-z0-9_-]{0,80}$/;
@@ -625,11 +630,13 @@ function TemplateCreateScreen({
625
630
  client,
626
631
  type,
627
632
  locales = [],
628
- onCreated
633
+ onCreated,
634
+ locale
629
635
  }) {
636
+ const tr = (0, import_client3.createAdminT)(locale);
630
637
  const addingLocale = type !== void 0;
631
638
  const [newType, setNewType] = (0, import_react2.useState)("");
632
- const [locale, setLocale] = (0, import_react2.useState)("");
639
+ const [targetLocale, setTargetLocale] = (0, import_react2.useState)("");
633
640
  const [subject, setSubject] = (0, import_react2.useState)("");
634
641
  const [html, setHtml] = (0, import_react2.useState)("");
635
642
  const [text, setText] = (0, import_react2.useState)("");
@@ -647,21 +654,21 @@ function TemplateCreateScreen({
647
654
  e.preventDefault();
648
655
  setError(null);
649
656
  const t = addingLocale ? type : newType.trim();
650
- const l = locale.trim() || null;
651
- if (!TYPE_RE.test(t))
652
- return setError("Type: lowercase letters, digits, - and _ (e.g. weekly-digest).");
653
- if (addingLocale && !l) return setError("Choose the locale to add, e.g. fr or fr-CA.");
654
- if (l && !LOCALE_RE.test(l)) return setError("Locale: a language tag such as fr, es or fr-CA.");
655
- if (!text.trim())
656
- return setError("The plain-text body is required \u2014 it is what every email client can show.");
657
+ const l = targetLocale.trim() || null;
658
+ if (!TYPE_RE.test(t)) return setError(tr("templates.create.errorType"));
659
+ if (addingLocale && !l) return setError(tr("templates.create.errorLocaleRequired"));
660
+ if (l && !LOCALE_RE.test(l)) return setError(tr("templates.create.errorLocale"));
661
+ if (!text.trim()) return setError(tr("templates.create.errorText"));
657
662
  setBusy(true);
658
663
  try {
659
664
  const exists = await client.getTemplate(t, l).then(
660
665
  () => true,
661
- (err) => !(err instanceof import_client.FonderieApiError && err.status === 404)
666
+ (err) => !(err instanceof import_client3.FonderieApiError && err.status === 404)
662
667
  );
663
668
  if (exists) {
664
- setError(`"${t}"${l ? ` (${l})` : ""} already exists \u2014 open it from the list to edit.`);
669
+ setError(
670
+ l ? tr("templates.create.existsLocale", { type: t, locale: l }) : tr("templates.create.exists", { type: t })
671
+ );
665
672
  return;
666
673
  }
667
674
  const input = { text, active: true };
@@ -670,17 +677,17 @@ function TemplateCreateScreen({
670
677
  await client.setTemplate(t, input, l);
671
678
  onCreated?.({ type: t, locale: l });
672
679
  } catch (err) {
673
- setError(err instanceof import_client.FonderieApiError ? err.explanation : String(err));
680
+ setError(err instanceof import_client3.FonderieApiError ? err.explanation : String(err));
674
681
  } finally {
675
682
  setBusy(false);
676
683
  }
677
684
  };
678
685
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: styles3.container, children: [
679
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h1", { style: styles3.title, children: addingLocale ? `Add a locale to ${type}` : "New template" }),
680
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { style: styles3.meta, children: addingLocale ? "Starts from the default copy. People whose locale matches receive this version; everyone else keeps the default." : "For an email your app sends that has no stored copy yet. The type must match what the app sends." }),
686
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h1", { style: styles3.title, children: addingLocale ? tr("templates.create.titleLocale", { type }) : tr("templates.create.titleNew") }),
687
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { style: styles3.meta, children: addingLocale ? tr("templates.create.hintLocale") : tr("templates.create.hintNew") }),
681
688
  /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("form", { style: styles3.form, onSubmit: (e) => void submit(e), children: [
682
689
  !addingLocale ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
683
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("label", { style: styles3.label, htmlFor: "new-template-type", children: "Type" }),
690
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("label", { style: styles3.label, htmlFor: "new-template-type", children: tr("templates.create.type") }),
684
691
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
685
692
  "input",
686
693
  {
@@ -694,25 +701,22 @@ function TemplateCreateScreen({
694
701
  }
695
702
  )
696
703
  ] }) : null,
697
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { style: styles3.label, htmlFor: "new-template-locale", children: [
698
- "Locale ",
699
- addingLocale ? "" : "(optional \u2014 empty is the default)"
700
- ] }),
704
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("label", { style: styles3.label, htmlFor: "new-template-locale", children: addingLocale ? tr("templates.create.locale") : tr("templates.create.localeOptional") }),
701
705
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
702
706
  "input",
703
707
  {
704
708
  id: "new-template-locale",
705
709
  style: styles3.input,
706
- value: locale,
710
+ value: targetLocale,
707
711
  placeholder: "fr",
708
712
  list: "new-template-locales",
709
713
  autoComplete: "off",
710
714
  spellCheck: false,
711
- onChange: (e) => setLocale(e.target.value)
715
+ onChange: (e) => setTargetLocale(e.target.value)
712
716
  }
713
717
  ),
714
718
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("datalist", { id: "new-template-locales", children: [...new Set(locales)].map((l) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: l }, l)) }),
715
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("label", { style: styles3.label, htmlFor: "new-template-subject", children: "Subject" }),
719
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("label", { style: styles3.label, htmlFor: "new-template-subject", children: tr("templates.subject") }),
716
720
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
717
721
  "input",
718
722
  {
@@ -722,7 +726,7 @@ function TemplateCreateScreen({
722
726
  onChange: (e) => setSubject(e.target.value)
723
727
  }
724
728
  ),
725
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("label", { style: styles3.label, htmlFor: "new-template-html", children: "HTML body" }),
729
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("label", { style: styles3.label, htmlFor: "new-template-html", children: tr("templates.htmlBody") }),
726
730
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
727
731
  "textarea",
728
732
  {
@@ -732,7 +736,7 @@ function TemplateCreateScreen({
732
736
  onChange: (e) => setHtml(e.target.value)
733
737
  }
734
738
  ),
735
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("label", { style: styles3.label, htmlFor: "new-template-text", children: "Plain-text body" }),
739
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("label", { style: styles3.label, htmlFor: "new-template-text", children: tr("templates.textBody") }),
736
740
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
737
741
  "textarea",
738
742
  {
@@ -743,7 +747,7 @@ function TemplateCreateScreen({
743
747
  }
744
748
  ),
745
749
  error ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { style: styles3.error, role: "alert", children: error }) : null,
746
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "submit", disabled: busy, style: styles3.button, children: busy ? "Creating\u2026" : addingLocale ? "Add locale" : "Create template" })
750
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "submit", disabled: busy, style: styles3.button, children: busy ? tr("templates.create.creating") : addingLocale ? tr("templates.create.submitLocale") : tr("templates.create.submitNew") })
747
751
  ] })
748
752
  ] });
749
753
  }