@churchapps/apphelper 0.2.31 → 0.2.33

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 (184) hide show
  1. package/.vscode/settings.json +6 -0
  2. package/dist/components/B1ShareModal.js +9 -12
  3. package/dist/components/B1ShareModal.js.map +1 -1
  4. package/dist/components/CreatePerson.js +4 -4
  5. package/dist/components/CreatePerson.js.map +1 -1
  6. package/dist/components/FormSubmissionEdit.js +3 -3
  7. package/dist/components/FormSubmissionEdit.js.map +1 -1
  8. package/dist/components/ImageEditor.d.ts.map +1 -1
  9. package/dist/components/ImageEditor.js +2 -1
  10. package/dist/components/ImageEditor.js.map +1 -1
  11. package/dist/components/InputBox.d.ts.map +1 -1
  12. package/dist/components/InputBox.js +4 -3
  13. package/dist/components/InputBox.js.map +1 -1
  14. package/dist/components/PersonAdd.js +1 -1
  15. package/dist/components/PersonAdd.js.map +1 -1
  16. package/dist/components/SupportModal.d.ts.map +1 -1
  17. package/dist/components/SupportModal.js +14 -5
  18. package/dist/components/SupportModal.js.map +1 -1
  19. package/dist/components/gallery/GalleryModal.js +6 -5
  20. package/dist/components/gallery/GalleryModal.js.map +1 -1
  21. package/dist/components/gallery/StockPhotos.js +4 -3
  22. package/dist/components/gallery/StockPhotos.js.map +1 -1
  23. package/dist/components/iconPicker/IconPicker.d.ts.map +1 -1
  24. package/dist/components/iconPicker/IconPicker.js +10 -3
  25. package/dist/components/iconPicker/IconPicker.js.map +1 -1
  26. package/dist/components/markdownEditor/MarkdownModal.d.ts.map +1 -1
  27. package/dist/components/markdownEditor/MarkdownModal.js +6 -4
  28. package/dist/components/markdownEditor/MarkdownModal.js.map +1 -1
  29. package/dist/components/notes/AddNote.js +1 -1
  30. package/dist/components/notes/AddNote.js.map +1 -1
  31. package/dist/components/notes/Conversation.js +5 -3
  32. package/dist/components/notes/Conversation.js.map +1 -1
  33. package/dist/components/notes/NewConversation.js +2 -2
  34. package/dist/components/notes/NewConversation.js.map +1 -1
  35. package/dist/components/notes/Notes.js +1 -1
  36. package/dist/components/notes/Notes.js.map +1 -1
  37. package/dist/components/reporting/ChartReport.d.ts.map +1 -1
  38. package/dist/components/reporting/ChartReport.js +2 -1
  39. package/dist/components/reporting/ChartReport.js.map +1 -1
  40. package/dist/components/reporting/ReportFilter.js +1 -1
  41. package/dist/components/reporting/ReportFilter.js.map +1 -1
  42. package/dist/components/reporting/ReportFilterField.d.ts.map +1 -1
  43. package/dist/components/reporting/ReportFilterField.js +2 -2
  44. package/dist/components/reporting/ReportFilterField.js.map +1 -1
  45. package/dist/components/reporting/ReportOutput.d.ts.map +1 -1
  46. package/dist/components/reporting/ReportOutput.js +6 -8
  47. package/dist/components/reporting/ReportOutput.js.map +1 -1
  48. package/dist/components/wrapper/ChurchList.d.ts.map +1 -1
  49. package/dist/components/wrapper/ChurchList.js +4 -2
  50. package/dist/components/wrapper/ChurchList.js.map +1 -1
  51. package/dist/components/wrapper/NavItem.d.ts.map +1 -1
  52. package/dist/components/wrapper/NavItem.js +5 -3
  53. package/dist/components/wrapper/NavItem.js.map +1 -1
  54. package/dist/components/wrapper/NewPrivateMessage.js +5 -5
  55. package/dist/components/wrapper/NewPrivateMessage.js.map +1 -1
  56. package/dist/components/wrapper/NotificationMenu.d.ts.map +1 -1
  57. package/dist/components/wrapper/NotificationMenu.js.map +1 -1
  58. package/dist/components/wrapper/PrivateMessageDetails.d.ts.map +1 -1
  59. package/dist/components/wrapper/PrivateMessageDetails.js +3 -1
  60. package/dist/components/wrapper/PrivateMessageDetails.js.map +1 -1
  61. package/dist/components/wrapper/UserMenu.d.ts.map +1 -1
  62. package/dist/components/wrapper/UserMenu.js +7 -6
  63. package/dist/components/wrapper/UserMenu.js.map +1 -1
  64. package/dist/donationComponents/DonationPage.js +6 -6
  65. package/dist/donationComponents/DonationPage.js.map +1 -1
  66. package/dist/donationComponents/components/BankForm.js +15 -15
  67. package/dist/donationComponents/components/BankForm.js.map +1 -1
  68. package/dist/donationComponents/components/CardForm.js +5 -5
  69. package/dist/donationComponents/components/CardForm.js.map +1 -1
  70. package/dist/donationComponents/components/DonationForm.js +22 -22
  71. package/dist/donationComponents/components/DonationForm.js.map +1 -1
  72. package/dist/donationComponents/components/FundDonation.d.ts.map +1 -1
  73. package/dist/donationComponents/components/FundDonation.js +4 -3
  74. package/dist/donationComponents/components/FundDonation.js.map +1 -1
  75. package/dist/donationComponents/components/FundDonations.d.ts.map +1 -1
  76. package/dist/donationComponents/components/FundDonations.js +2 -1
  77. package/dist/donationComponents/components/FundDonations.js.map +1 -1
  78. package/dist/donationComponents/components/NonAuthDonationInner.js +22 -23
  79. package/dist/donationComponents/components/NonAuthDonationInner.js.map +1 -1
  80. package/dist/donationComponents/components/PaymentMethods.js +8 -6
  81. package/dist/donationComponents/components/PaymentMethods.js.map +1 -1
  82. package/dist/donationComponents/components/RecurringDonations.js +7 -6
  83. package/dist/donationComponents/components/RecurringDonations.js.map +1 -1
  84. package/dist/donationComponents/components/RecurringDonationsEdit.js +13 -13
  85. package/dist/donationComponents/components/RecurringDonationsEdit.js.map +1 -1
  86. package/dist/donationComponents/modals/DonationPreviewModal.js +32 -12
  87. package/dist/donationComponents/modals/DonationPreviewModal.js.map +1 -1
  88. package/dist/helpers/Locale.d.ts +4 -0
  89. package/dist/helpers/Locale.d.ts.map +1 -1
  90. package/dist/helpers/Locale.js +22 -4
  91. package/dist/helpers/Locale.js.map +1 -1
  92. package/dist/helpers/PersonHelper.d.ts.map +1 -1
  93. package/dist/helpers/PersonHelper.js +2 -1
  94. package/dist/helpers/PersonHelper.js.map +1 -1
  95. package/dist/helpers/ReportHelper.d.ts.map +1 -1
  96. package/dist/helpers/ReportHelper.js.map +1 -1
  97. package/dist/pageComponents/LoginPage.js +5 -8
  98. package/dist/pageComponents/LoginPage.js.map +1 -1
  99. package/dist/pageComponents/components/Forgot.js +11 -10
  100. package/dist/pageComponents/components/Forgot.js.map +1 -1
  101. package/dist/pageComponents/components/LoginSetPassword.js +8 -7
  102. package/dist/pageComponents/components/LoginSetPassword.js.map +1 -1
  103. package/dist/pageComponents/components/Register.d.ts.map +1 -1
  104. package/dist/pageComponents/components/Register.js +6 -8
  105. package/dist/pageComponents/components/Register.js.map +1 -1
  106. package/dist/pageComponents/components/SelectChurchModal.d.ts.map +1 -1
  107. package/dist/pageComponents/components/SelectChurchModal.js +3 -2
  108. package/dist/pageComponents/components/SelectChurchModal.js.map +1 -1
  109. package/dist/pageComponents/components/SelectChurchRegister.d.ts.map +1 -1
  110. package/dist/pageComponents/components/SelectChurchRegister.js +14 -19
  111. package/dist/pageComponents/components/SelectChurchRegister.js.map +1 -1
  112. package/dist/pageComponents/components/SelectChurchSearch.js +4 -4
  113. package/dist/pageComponents/components/SelectChurchSearch.js.map +1 -1
  114. package/dist/public/locales/de.json +271 -0
  115. package/dist/public/locales/en.json +269 -20
  116. package/dist/public/locales/es.json +268 -17
  117. package/dist/public/locales/fr.json +271 -0
  118. package/dist/public/locales/hi.json +271 -0
  119. package/dist/public/locales/it.json +271 -0
  120. package/dist/public/locales/ko.json +271 -0
  121. package/dist/public/locales/no.json +271 -0
  122. package/dist/public/locales/pt.json +271 -0
  123. package/dist/public/locales/ru.json +271 -0
  124. package/dist/public/locales/tl.json +271 -0
  125. package/dist/public/locales/zh.json +271 -0
  126. package/package.json +1 -1
  127. package/public/locales/de.json +271 -0
  128. package/public/locales/en.json +269 -20
  129. package/public/locales/es.json +268 -17
  130. package/public/locales/fr.json +271 -0
  131. package/public/locales/hi.json +271 -0
  132. package/public/locales/it.json +271 -0
  133. package/public/locales/ko.json +271 -0
  134. package/public/locales/no.json +271 -0
  135. package/public/locales/pt.json +271 -0
  136. package/public/locales/ru.json +271 -0
  137. package/public/locales/tl.json +271 -0
  138. package/public/locales/zh.json +271 -0
  139. package/src/components/B1ShareModal.tsx +10 -10
  140. package/src/components/CreatePerson.tsx +5 -5
  141. package/src/components/FormSubmissionEdit.tsx +5 -5
  142. package/src/components/ImageEditor.tsx +2 -1
  143. package/src/components/InputBox.tsx +4 -3
  144. package/src/components/PersonAdd.tsx +3 -3
  145. package/src/components/SupportModal.tsx +5 -4
  146. package/src/components/gallery/GalleryModal.tsx +6 -6
  147. package/src/components/gallery/StockPhotos.tsx +3 -3
  148. package/src/components/iconPicker/IconPicker.tsx +4 -3
  149. package/src/components/markdownEditor/MarkdownModal.tsx +5 -4
  150. package/src/components/notes/AddNote.tsx +2 -2
  151. package/src/components/notes/Conversation.tsx +3 -3
  152. package/src/components/notes/NewConversation.tsx +3 -3
  153. package/src/components/notes/Notes.tsx +2 -2
  154. package/src/components/reporting/ChartReport.tsx +2 -1
  155. package/src/components/reporting/ReportFilter.tsx +2 -2
  156. package/src/components/reporting/ReportFilterField.tsx +4 -3
  157. package/src/components/reporting/ReportOutput.tsx +6 -8
  158. package/src/components/wrapper/ChurchList.tsx +13 -11
  159. package/src/components/wrapper/NavItem.tsx +9 -7
  160. package/src/components/wrapper/NewPrivateMessage.tsx +6 -6
  161. package/src/components/wrapper/NotificationMenu.tsx +0 -1
  162. package/src/components/wrapper/PrivateMessageDetails.tsx +2 -1
  163. package/src/components/wrapper/UserMenu.tsx +8 -9
  164. package/src/donationComponents/DonationPage.tsx +7 -7
  165. package/src/donationComponents/components/BankForm.tsx +16 -16
  166. package/src/donationComponents/components/CardForm.tsx +6 -6
  167. package/src/donationComponents/components/DonationForm.tsx +21 -21
  168. package/src/donationComponents/components/FundDonation.tsx +4 -3
  169. package/src/donationComponents/components/FundDonations.tsx +2 -1
  170. package/src/donationComponents/components/NonAuthDonationInner.tsx +22 -22
  171. package/src/donationComponents/components/PaymentMethods.tsx +7 -7
  172. package/src/donationComponents/components/RecurringDonations.tsx +4 -4
  173. package/src/donationComponents/components/RecurringDonationsEdit.tsx +14 -14
  174. package/src/donationComponents/modals/DonationPreviewModal.tsx +13 -13
  175. package/src/helpers/Locale.ts +22 -39
  176. package/src/helpers/PersonHelper.ts +2 -1
  177. package/src/helpers/ReportHelper.ts +0 -1
  178. package/src/pageComponents/LoginPage.tsx +6 -6
  179. package/src/pageComponents/components/Forgot.tsx +10 -10
  180. package/src/pageComponents/components/LoginSetPassword.tsx +8 -8
  181. package/src/pageComponents/components/Register.tsx +7 -13
  182. package/src/pageComponents/components/SelectChurchModal.tsx +4 -2
  183. package/src/pageComponents/components/SelectChurchRegister.tsx +16 -21
  184. package/src/pageComponents/components/SelectChurchSearch.tsx +5 -5
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import { ApiHelper } from "../../helpers";
2
+ import { ApiHelper, Locale } from "../../helpers";
3
3
  import { InputBox } from "../../components";
4
4
  import { StripePaymentMethod, SubscriptionInterface } from "@churchapps/helpers";
5
5
  import { FormControl, Grid, InputLabel, MenuItem, Select, SelectChangeEvent, TextField } from "@mui/material"
@@ -20,16 +20,16 @@ export const RecurringDonationsEdit: React.FC<Props> = (props) => {
20
20
  sub.default_payment_method = pm.type === "card" ? pm.id : null;
21
21
  sub.default_source = pm.type === "bank" ? pm.id : null;
22
22
  }
23
- ApiHelper.post("/subscriptions", [sub], "GivingApi").then(() => props.subscriptionUpdated("Recurring donation updated."))
23
+ ApiHelper.post("/subscriptions", [sub], "GivingApi").then(() => props.subscriptionUpdated(Locale.label("donation.donationForm.recurringUpdated")))
24
24
  }
25
25
 
26
26
  const handleDelete = () => {
27
- const conf = window.confirm("Are you sure you want to delete this recurring donation?");
27
+ const conf = window.confirm(Locale.label("donation.donationForm.confirmDelete"));
28
28
  if (!conf) return;
29
29
  let promises = [];
30
30
  promises.push(ApiHelper.delete("/subscriptions/" + props.editSubscription.id, "GivingApi"));
31
31
  promises.push(ApiHelper.delete("/subscriptionfunds/subscription/" + props.editSubscription.id, "GivingApi"));
32
- Promise.all(promises).then(() => props.subscriptionUpdated("Recurring donation canceled."));
32
+ Promise.all(promises).then(() => props.subscriptionUpdated(Locale.label("donation.donationForm.cancelled")));
33
33
  }
34
34
 
35
35
  const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement> | SelectChangeEvent<string>) => {
@@ -56,21 +56,21 @@ export const RecurringDonationsEdit: React.FC<Props> = (props) => {
56
56
  <Grid container spacing={3}>
57
57
  <Grid item md={6} xs={12}>
58
58
  <FormControl fullWidth>
59
- <InputLabel>Method</InputLabel>
60
- <Select label="Method" name="method" aria-label="method" value={editSubscription.default_payment_method || editSubscription.default_source} className="capitalize" onChange={handleChange}>
59
+ <InputLabel>{Locale.label("donation.donationForm.method")}</InputLabel>
60
+ <Select label={Locale.label("donation.donationForm.method")} name="method" aria-label="method" value={editSubscription.default_payment_method || editSubscription.default_source} className="capitalize" onChange={handleChange}>
61
61
  {props.paymentMethods.map((paymentMethod: any, i: number) => <MenuItem key={i} value={paymentMethod.id}>{paymentMethod.name} ****{paymentMethod.last4}</MenuItem>)}
62
62
  </Select>
63
63
  </FormControl>
64
64
  </Grid>
65
65
  <Grid item md={6} xs={12}>
66
66
  <FormControl fullWidth>
67
- <InputLabel>Frequency</InputLabel>
68
- <Select label="Frequency" name="interval" aria-label="interval" value={interval} onChange={handleChange}>
69
- <MenuItem value="one_week">Weekly</MenuItem>
70
- <MenuItem value="two_week">Bi-Weekly</MenuItem>
71
- <MenuItem value="one_month">Monthly</MenuItem>
72
- <MenuItem value="three_month">Quarterly</MenuItem>
73
- <MenuItem value="one_year">Annually</MenuItem>
67
+ <InputLabel>{Locale.label("donation.donationForm.frequency")}</InputLabel>
68
+ <Select label={Locale.label("donation.donationForm.frequency")} name="interval" aria-label="interval" value={interval} onChange={handleChange}>
69
+ <MenuItem value="one_week">{Locale.label("donation.donationForm.weekly")}</MenuItem>
70
+ <MenuItem value="two_week">{Locale.label("donation.donationForm.biWeekly")}</MenuItem>
71
+ <MenuItem value="one_month">{Locale.label("donation.donationForm.monthly")}</MenuItem>
72
+ <MenuItem value="three_month">{Locale.label("donation.donationForm.quarterly")}</MenuItem>
73
+ <MenuItem value="one_year">{Locale.label("donation.donationForm.annually")}</MenuItem>
74
74
  </Select>
75
75
  </FormControl>
76
76
  </Grid>
@@ -86,7 +86,7 @@ export const RecurringDonationsEdit: React.FC<Props> = (props) => {
86
86
  }, [props.editSubscription]);
87
87
 
88
88
  return (
89
- <InputBox aria-label="person-details-box" headerIcon="person" headerText="Edit Recurring Donation" ariaLabelSave="save-button" ariaLabelDelete="delete-button" cancelFunction={handleCancel} deleteFunction={handleDelete} saveFunction={handleSave}>
89
+ <InputBox aria-label="person-details-box" headerIcon="person" headerText={Locale.label("donation.donationForm.editRecurring")} ariaLabelSave="save-button" ariaLabelDelete="delete-button" cancelFunction={handleCancel} deleteFunction={handleDelete} saveFunction={handleSave}>
90
90
  {getFields()}
91
91
  </InputBox>
92
92
  );
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import { DateHelper, CurrencyHelper } from "../../helpers";
2
+ import { DateHelper, CurrencyHelper, Locale } from "../../helpers";
3
3
  import { StripeDonationInterface } from "@churchapps/helpers";
4
4
  import { Table, TableBody, TableRow, TableCell, Dialog, DialogTitle, DialogContent, DialogActions, Button } from "@mui/material"
5
5
 
@@ -38,28 +38,28 @@ export const DonationPreviewModal: React.FC<Props> = (props) => {
38
38
  <DialogContent>
39
39
  <Table>
40
40
  <TableBody>
41
- <TableRow><TableCell>Name:</TableCell><TableCell>{props.donation.person.name}</TableCell></TableRow>
42
- <TableRow><TableCell>Payment Method:</TableCell><TableCell className="capitalize">{props.paymentMethodName}</TableCell></TableRow>
43
- <TableRow><TableCell>Type:</TableCell><TableCell>{donationType[props.donationType]}</TableCell></TableRow>
41
+ <TableRow><TableCell>{Locale.label("person.name")}:</TableCell><TableCell>{props.donation.person.name}</TableCell></TableRow>
42
+ <TableRow><TableCell>{Locale.label("donation.preview.method")}:</TableCell><TableCell className="capitalize">{props.paymentMethodName}</TableCell></TableRow>
43
+ <TableRow><TableCell>{Locale.label("donation.preview.type")}:</TableCell><TableCell>{donationType[props.donationType]}</TableCell></TableRow>
44
44
  {props.donationType === "once"
45
- && <TableRow><TableCell>Donation Date:</TableCell><TableCell>{DateHelper.formatHtml5Date(new Date(props.donation.billing_cycle_anchor))}</TableCell></TableRow>
45
+ && <TableRow><TableCell>{Locale.label("donation.preview.date")}:</TableCell><TableCell>{DateHelper.formatHtml5Date(new Date(props.donation.billing_cycle_anchor))}</TableCell></TableRow>
46
46
  }
47
- <TableRow><TableCell>Notes:</TableCell><TableCell>{props.donation.notes}</TableCell></TableRow>
47
+ <TableRow><TableCell>{Locale.label("donation.preview.weekly")}:</TableCell><TableCell>{props.donation.notes}</TableCell></TableRow>
48
48
  {props.donationType === "recurring"
49
49
  && <>
50
- <TableRow><TableCell>Starting On:</TableCell><TableCell>{DateHelper.formatHtml5Date(new Date(props.donation.billing_cycle_anchor))}</TableCell></TableRow>
51
- <TableRow><TableCell>Recurring Every:</TableCell><TableCell className="capitalize">{formatInterval()}</TableCell></TableRow>
50
+ <TableRow><TableCell>{Locale.label("donation.preview.startingOn")}:</TableCell><TableCell>{DateHelper.formatHtml5Date(new Date(props.donation.billing_cycle_anchor))}</TableCell></TableRow>
51
+ <TableRow><TableCell>{Locale.label("donation.preview.every")}:</TableCell><TableCell className="capitalize">{formatInterval()}</TableCell></TableRow>
52
52
  </>
53
53
  }
54
- <TableRow><TableCell>Funds:</TableCell><TableCell>{props.donation.funds.map((fund: any, i: number) => <p key={i}>{CurrencyHelper.formatCurrency(fund.amount)} - {fund.name}</p>)}</TableCell></TableRow>
55
- {props.payFee > 0 && <TableRow><TableCell>Transaction Fee:</TableCell><TableCell>{CurrencyHelper.formatCurrency(props.payFee)}</TableCell></TableRow>}
56
- <TableRow><TableCell>Total:</TableCell><TableCell><h4>{CurrencyHelper.formatCurrency(props.donation.amount)}</h4></TableCell></TableRow>
54
+ <TableRow><TableCell>{Locale.label("donation.preview.funds")}:</TableCell><TableCell>{props.donation.funds.map((fund: any, i: number) => <p key={i}>{CurrencyHelper.formatCurrency(fund.amount)} - {fund.name}</p>)}</TableCell></TableRow>
55
+ {props.payFee > 0 && <TableRow><TableCell>{Locale.label("donation.preview.fee")}:</TableCell><TableCell>{CurrencyHelper.formatCurrency(props.payFee)}</TableCell></TableRow>}
56
+ <TableRow><TableCell>{Locale.label("donation.preview.total")}:</TableCell><TableCell><h4>{CurrencyHelper.formatCurrency(props.donation.amount)}</h4></TableCell></TableRow>
57
57
  </TableBody>
58
58
  </Table>
59
59
  </DialogContent>
60
60
  <DialogActions>
61
- <Button onClick={props.onHide} variant="outlined" aria-label="cancel-button">Cancel</Button>
62
- <Button onClick={handleClick} variant="contained" aria-label="donate-button" disabled={isLoading}>Donate</Button>
61
+ <Button onClick={props.onHide} variant="outlined" aria-label="cancel-button">{Locale.label("donation.common.cancel")}</Button>
62
+ <Button onClick={handleClick} variant="contained" aria-label="donate-button" disabled={isLoading}>{Locale.label("donation.preview.donate")}</Button>
63
63
  </DialogActions>
64
64
  </Dialog>
65
65
  );
@@ -8,12 +8,16 @@ import HttpBackend from 'i18next-http-backend';
8
8
 
9
9
  export class Locale {
10
10
 
11
+ private static supportedLanguages = ["de", "en", "es", "fr", "hi", "it", "ko", "no", "pt", "ru", "tl", "zh"];
12
+ private static extraCodes: {[key: string]: string[]} = {no: ["nb", "nn"]}
13
+
11
14
  private static keys:any = {}
12
15
 
13
16
  static init = async (backends:string[]) => {
14
- const l = navigator.language.split("-")[0];
15
- const langs = (l==="en") ? [l] : ["en", l];
16
- console.log("LANGUAGE", navigator.language, l, langs);
17
+ let l = navigator.language.split("-")[0];
18
+ l = Object.keys(this.extraCodes).find(code => this.extraCodes[code].includes(l)) || l
19
+ const notSupported = this.supportedLanguages.indexOf(l) === -1
20
+ const langs = (l==="en" || notSupported) ? ["en"] : ["en", l];
17
21
 
18
22
  let result = {};
19
23
  for (let lang of langs) {
@@ -21,12 +25,26 @@ export class Locale {
21
25
  let url = backend.replace("{{lng}}", lang);
22
26
  console.log(url);
23
27
  const data = await fetch(url).then((response) => response.json());
24
- result = {...result, ...data};
28
+ result = this.deepMerge(result, data);
25
29
  }
26
30
  }
27
31
  this.keys = result;
28
32
  }
29
33
 
34
+ private static deepMerge(target:any, source:any) {
35
+ for (const key in source) {
36
+ if (this.isObject(source[key])) {
37
+ if (!target[key]) Object.assign(target, { [key]: {} });
38
+ this.deepMerge(target[key], source[key]);
39
+ } else Object.assign(target, { [key]: source[key] });
40
+ }
41
+ return target;
42
+ }
43
+
44
+ private static isObject(obj:any) {
45
+ return obj && typeof obj === 'object' && !Array.isArray(obj);
46
+ }
47
+
30
48
  static label(key:string) {
31
49
  const parts = key.split(".");
32
50
  let result = key;
@@ -42,40 +60,5 @@ export class Locale {
42
60
  return result;
43
61
  }
44
62
 
45
- /*
46
- //'/locales/{{lng}}.json'
47
- static init = async (backends:string[]) => {
48
-
49
- const backendOptions = backends.map((path) => ({ loadPath: path }));
50
-
51
-
52
- console.log("backend options", backendOptions)
53
- console.log({backend: {
54
- backends: backends.map(() => HttpBackend),
55
- backendOptions,
56
- }})
57
-
58
- await i18n
59
- .use(Backend)
60
- .use(LanguageDetector)
61
- .use(initReactI18next)
62
- .init({
63
- fallbackLng: 'en',
64
- debug: true,
65
- interpolation: {
66
- escapeValue: false, // React already does escaping
67
- },
68
- backend: {
69
- backends: backends.map(() => HttpBackend),
70
- backendOptions,
71
- },
72
- supportedLngs: ['en', 'es'],
73
- });
74
- }
75
-
76
- static label(key:string) {
77
- return i18n.t(key);
78
- }
79
- */
80
63
 
81
64
  }
@@ -1,5 +1,6 @@
1
1
  import { PersonInterface, ContactInfoInterface } from "@churchapps/helpers";
2
2
  import { CommonEnvironmentHelper } from "./CommonEnvironmentHelper";
3
+ import { Locale } from "./Locale";
3
4
 
4
5
  export class PersonHelper {
5
6
 
@@ -13,7 +14,7 @@ export class PersonHelper {
13
14
  let ageDifMs = Date.now() - new Date(birthdate).getTime();
14
15
  let ageDate = new Date(ageDifMs);
15
16
  let years = Math.abs(ageDate.getUTCFullYear() - 1970);
16
- return years + " years";
17
+ return years + " " + Locale.label("person.years");
17
18
  }
18
19
  else return "";
19
20
  }
@@ -1,4 +1,3 @@
1
- import { parse } from "path";
2
1
  import { ColumnInterface } from "@churchapps/helpers";
3
2
  import { DateHelper } from "./DateHelper";
4
3
 
@@ -1,7 +1,7 @@
1
1
  import * as React from "react";
2
2
  import { ErrorMessages, FloatingSupport, Loading } from "../components";
3
3
  import { LoginResponseInterface, UserContextInterface, ChurchInterface, UserInterface, LoginUserChurchInterface } from "@churchapps/helpers";
4
- import { AnalyticsHelper, ApiHelper, ArrayHelper, UserHelper } from "../helpers";
4
+ import { AnalyticsHelper, ApiHelper, ArrayHelper, Locale, UserHelper } from "../helpers";
5
5
  import { useCookies } from "react-cookie"
6
6
  import jwt_decode from "jwt-decode"
7
7
  import { Register } from "./components/Register"
@@ -183,7 +183,7 @@ export const LoginPage: React.FC<Props> = ({ showLogo = true, loginContainerCssP
183
183
  UserHelper.selectChurch(props.context, churchId, null).then(() => { continueLoginProcess() });
184
184
  } catch (err) {
185
185
  console.log("Error in selecting church: ", err)
186
- setErrors(["Error in selecting church. Please verify and try again"])
186
+ setErrors([Locale.label("login.validate.selectChurch")])
187
187
  loginFormRef?.current?.setSubmitting(false);
188
188
  }
189
189
 
@@ -192,7 +192,7 @@ export const LoginPage: React.FC<Props> = ({ showLogo = true, loginContainerCssP
192
192
  const handleLoginErrors = (errors: string[]) => {
193
193
  setWelcomeBackName("");
194
194
  console.log(errors);
195
- setErrors(["Invalid login. Please check your email or password."]);
195
+ setErrors([Locale.label("login.validate.invalid")]);
196
196
  }
197
197
 
198
198
  const login = async (data: any) => {
@@ -209,8 +209,8 @@ export const LoginPage: React.FC<Props> = ({ showLogo = true, loginContainerCssP
209
209
  }
210
210
  };
211
211
 
212
- const getWelcomeBack = () => { if (welcomeBackName !== "") return (<><Alert severity="info">Welcome back, <b>{welcomeBackName}</b>! Please wait while we load your data.</Alert><Loading /></>); }
213
- const getCheckEmail = () => { if (new URLSearchParams(location?.search).get("checkEmail") === "1") return <Alert severity="info"> Thank you for registering. Please check your email to continue.</Alert> }
212
+ const getWelcomeBack = () => { if (welcomeBackName !== "") return (<><Alert severity="info">{Locale.label("login.welcomeName").replace("{}", welcomeBackName)}</Alert><Loading /></>); }
213
+ const getCheckEmail = () => { if (new URLSearchParams(location?.search).get("checkEmail") === "1") return <Alert severity="info">{Locale.label("login.registerThankYou")}</Alert> }
214
214
  const handleRegisterCallback = () => { setShowForgot(false); setShowRegister(true); }
215
215
  const handleLoginCallback = () => { setShowForgot(false); setShowRegister(false); }
216
216
  const handleChurchRegistered = (church: ChurchInterface) => { registeredChurch = church; setShowRegister(false); console.log("Updated VERSION********") }
@@ -218,7 +218,7 @@ export const LoginPage: React.FC<Props> = ({ showLogo = true, loginContainerCssP
218
218
  const getInputBox = () => {
219
219
  if (showRegister) return (
220
220
  <Box id="loginBox" sx={{ backgroundColor: "#FFF", border: "1px solid #CCC", borderRadius: "5px", padding: "20px" }}>
221
- <Typography component="h2" sx={{ fontSize: "32px", fontWeight: 500, lineHeight: 1.2, margin: "0 0 8px 0" }}>Create an Account</Typography>
221
+ <Typography component="h2" sx={{ fontSize: "32px", fontWeight: 500, lineHeight: 1.2, margin: "0 0 8px 0" }}>{Locale.label("login.createAccount")}</Typography>
222
222
  <Register updateErrors={setErrors} appName={props.appName} appUrl={cleanAppUrl()} loginCallback={handleLoginCallback} userRegisteredCallback={props.userRegisteredCallback} />
223
223
  </Box>
224
224
  );
@@ -1,5 +1,5 @@
1
1
  import React, { FormEventHandler } from "react";
2
- import { ApiHelper } from "../../helpers";
2
+ import { ApiHelper, Locale } from "../../helpers";
3
3
  import { ErrorMessages } from "../../components";
4
4
  import { ResetPasswordRequestInterface, ResetPasswordResponseInterface } from "@churchapps/helpers";
5
5
  import { Stack, TextField, Box, Typography } from "@mui/material";
@@ -24,8 +24,8 @@ export const Forgot: React.FC<Props> = props => {
24
24
 
25
25
  const validate = () => {
26
26
  const result = [];
27
- if (!email) result.push("Please enter your email address.");
28
- else if (!validateEmail(email)) result.push("Please enter a valid email address.");
27
+ if (!email) result.push(Locale.label("login.validate.email"));
28
+ else if (!validateEmail(email)) result.push(Locale.label("login.validate.email"));
29
29
  setErrors(result);
30
30
  return result.length === 0;
31
31
  }
@@ -40,7 +40,7 @@ export const Forgot: React.FC<Props> = props => {
40
40
  setErrors([]);
41
41
  setSuccessMessage(
42
42
  <Typography textAlign="center" marginTop="35px">
43
- Password reset email sent! <br /><br /><a href="about:blank" className="text-decoration" onClick={(e) => { e.preventDefault(); props.loginCallback(); }}>Go to Login</a>
43
+ {Locale.label("login.resetSent")} <br /><br /><a href="about:blank" className="text-decoration" onClick={(e) => { e.preventDefault(); props.loginCallback(); }}>{Locale.label("login.goLogin")}</a>
44
44
  </Typography>
45
45
  );
46
46
  setEmail("");
@@ -54,22 +54,22 @@ export const Forgot: React.FC<Props> = props => {
54
54
 
55
55
  return (
56
56
  <Box id="loginBox" sx={{ backgroundColor: "#FFF", border: "1px solid #CCC", borderRadius: "5px", padding: "20px" }}>
57
- <Typography component="h2" sx={{ fontSize: "32px", fontWeight: 500, lineHeight: 1.2, margin: "0 0 8px 0" }}>Reset Password</Typography>
57
+ <Typography component="h2" sx={{ fontSize: "32px", fontWeight: 500, lineHeight: 1.2, margin: "0 0 8px 0" }}>{Locale.label("login.resetPassword")}</Typography>
58
58
 
59
59
  <form onSubmit={reset}>
60
- <p>Enter your email address to request a password reset.</p>
60
+ <p>{Locale.label("login.resetInstructions")}</p>
61
61
  <ErrorMessages errors={errors} />
62
62
  {successMessage}
63
63
  {!successMessage && (
64
64
  <>
65
- <TextField fullWidth autoFocus label="Email" aria-label="email" id="email" name="email" value={email} onChange={handleChange} placeholder="Email address" onKeyDown={(e: React.KeyboardEvent<HTMLInputElement>) => e.key === "Enter" && reset} />
65
+ <TextField fullWidth autoFocus label={Locale.label("login.email")} aria-label="email" id="email" name="email" value={email} onChange={handleChange} placeholder={Locale.label("login.email")} onKeyDown={(e: React.KeyboardEvent<HTMLInputElement>) => e.key === "Enter" && reset} />
66
66
  <br />
67
67
  <Box sx={{ textAlign: "right", marginY: 1 }}>
68
- <a href="about:blank" className="text-decoration" onClick={(e) => { e.preventDefault(); props.registerCallback(); }}>Register</a> &nbsp; | &nbsp;
69
- <a href="about:blank" className="text-decoration" onClick={(e) => { e.preventDefault(); props.loginCallback(); }}>Login</a>&nbsp;
68
+ <a href="about:blank" className="text-decoration" onClick={(e) => { e.preventDefault(); props.registerCallback(); }}>{Locale.label("login.register")}</a> &nbsp; | &nbsp;
69
+ <a href="about:blank" className="text-decoration" onClick={(e) => { e.preventDefault(); props.loginCallback(); }}>{Locale.label("login.login")}</a>&nbsp;
70
70
  </Box>
71
71
  <Stack direction="row" sx={{ marginTop: 1.5 }} spacing={1} justifyContent="flex-end">
72
- <LoadingButton loading={isSubmitting} variant="contained" type="submit" disabled={isSubmitting}>Reset</LoadingButton>
72
+ <LoadingButton loading={isSubmitting} variant="contained" type="submit" disabled={isSubmitting}>{Locale.label("login.reset")}</LoadingButton>
73
73
  </Stack>
74
74
  </>
75
75
  )}
@@ -2,7 +2,7 @@ import React from "react";
2
2
  import { InputBox } from "../../components";
3
3
  import { TextField } from "@mui/material";
4
4
  import { LoginResponseInterface, UserInterface } from "@churchapps/helpers";
5
- import { ApiHelper } from "../../helpers";
5
+ import { ApiHelper, Locale } from "../../helpers";
6
6
 
7
7
  interface Props {
8
8
  appName: string,
@@ -21,9 +21,9 @@ export const LoginSetPassword: React.FC<Props> = props => {
21
21
 
22
22
  const validate = () => {
23
23
  const result = [];
24
- if (!password) result.push("Please enter your password.");
25
- else if (password.length < 8) result.push("Please enter at least an 8 character password.");
26
- else if (password !== verifyPassword) result.push("Passwords do not match");
24
+ if (!password) result.push(Locale.label("login.validate.password"));
25
+ else if (password.length < 8) result.push(Locale.label("login.validate.passwordLength"));
26
+ else if (password !== verifyPassword) result.push(Locale.label("login.validate.passwordMatch"));
27
27
  props.setErrors(result);
28
28
  return result.length === 0;
29
29
  }
@@ -54,10 +54,10 @@ export const LoginSetPassword: React.FC<Props> = props => {
54
54
  React.useEffect(loadUser, []); //eslint-disable-line
55
55
 
56
56
  return (
57
- <InputBox headerText="Set Password" saveFunction={submitChangePassword} saveButtonType="submit" saveText={(props.isSubmitting || !user) ? "Please wait..." : "Sign in"} isSubmitting={props.isSubmitting}>
58
- {user && <p style={{ marginTop: 0, marginBottom: 0 }}>Welcome back {user.firstName}.</p>}
59
- <TextField fullWidth name="password" type="password" label="Set Password" value={password} onChange={(e) => { e.preventDefault(); setPassword(e.target.value) }} />
60
- <TextField fullWidth name="verifyPassword" type="password" label="Verify Password" value={verifyPassword} onChange={(e) => { e.preventDefault(); setVerifyPassword(e.target.value) }} />
57
+ <InputBox headerText={Locale.label("login.setPassword")} saveFunction={submitChangePassword} saveButtonType="submit" saveText={(props.isSubmitting || !user) ? Locale.label("common.pleaseWait") : Locale.label("login.signIn")} isSubmitting={props.isSubmitting}>
58
+ {user && <p style={{ marginTop: 0, marginBottom: 0 }}>{Locale.label("login.welcomeBack")} {user.firstName}.</p>}
59
+ <TextField fullWidth name="password" type="password" label={Locale.label("login.setPassword")} value={password} onChange={(e) => { e.preventDefault(); setPassword(e.target.value) }} />
60
+ <TextField fullWidth name="verifyPassword" type="password" label={Locale.label("login.verifyPassword")} value={verifyPassword} onChange={(e) => { e.preventDefault(); setVerifyPassword(e.target.value) }} />
61
61
  </InputBox>
62
62
  );
63
63
  }
@@ -1,6 +1,6 @@
1
1
  import React, { FormEventHandler } from "react";
2
2
  import { LoginResponseInterface, RegisterUserInterface, UserInterface } from "@churchapps/helpers";
3
- import { AnalyticsHelper, ApiHelper } from "../../helpers";
3
+ import { AnalyticsHelper, ApiHelper, Locale } from "../../helpers";
4
4
  import { ErrorMessages } from "../../components";
5
5
  import { Button, Stack, TextField, Link } from "@mui/material";
6
6
 
@@ -52,10 +52,10 @@ export const Register: React.FC<Props> = (props) => {
52
52
 
53
53
  const validate = () => {
54
54
  let errors = [];
55
- if (!user.email?.trim()) errors.push("Please enter your email address.");
56
- else if (!validateEmail(user.email)) errors.push("Please enter a valid email address.");
57
- if (!user.firstName?.trim()) errors.push("Please enter your first name.");
58
- if (!user.lastName?.trim()) errors.push("Please enter your last name.");
55
+ if (!user.email?.trim()) errors.push(Locale.label("login.validate.email"));
56
+ else if (!validateEmail(user.email)) errors.push(Locale.label("login.validate.email"));
57
+ if (!user.firstName?.trim()) errors.push(Locale.label("login.validate.firstName"));
58
+ if (!user.lastName?.trim()) errors.push(Locale.label("login.validate.lastName"));
59
59
  setErrors(errors);
60
60
  return errors.length === 0;
61
61
  }
@@ -79,12 +79,6 @@ export const Register: React.FC<Props> = (props) => {
79
79
  }
80
80
  };
81
81
 
82
- const getThankYou = () => (
83
- <>
84
- <p>Thank you for registering. Please check your email to continue.</p>
85
- </>
86
- )
87
-
88
82
  const getForm = () => (<>
89
83
  <ErrorMessages errors={errors} />
90
84
  <form onSubmit={register}>
@@ -93,7 +87,7 @@ export const Register: React.FC<Props> = (props) => {
93
87
  <TextField fullWidth type="email" name="email" label="Email" value={user.email} onChange={handleChange} />
94
88
  <br />
95
89
  <Stack direction="row" sx={{ marginTop: 1 }} spacing={1} justifyContent="end">
96
- {props.loginCallback && (<Button variant="text" onClick={(e) => { e.preventDefault(); props.loginCallback(); }}>Login</Button>)}
90
+ {props.loginCallback && (<Button variant="text" onClick={(e) => { e.preventDefault(); props.loginCallback(); }}>{Locale.label("login.login")}</Button>)}
97
91
  <Button id="signInButton" variant="contained" disableElevation type="submit" disabled={isSubmitting} color="primary" onClick={register} sx={{ "&:focus": { outline: "none" } }}>
98
92
  {isSubmitting ? "Please wait..." : "Register"}
99
93
  </Button>
@@ -101,7 +95,7 @@ export const Register: React.FC<Props> = (props) => {
101
95
  </form>
102
96
  </>)
103
97
 
104
- if (registered) return getThankYou();
98
+ if (registered) return (<p>{Locale.label("login.registerThankYou")}</p>);
105
99
  else return getForm();
106
100
 
107
101
  };
@@ -4,6 +4,7 @@ import { SelectChurchSearch } from "./SelectChurchSearch";
4
4
  import { SelectableChurch } from "./SelectableChurch";
5
5
  import { ErrorMessages } from "../../components"
6
6
  import { Dialog, DialogContent, DialogTitle, Icon, IconButton, Tooltip } from "@mui/material";
7
+ import { Locale } from "../../helpers";
7
8
 
8
9
  interface Props {
9
10
  appName: string,
@@ -25,13 +26,14 @@ export const SelectChurchModal: React.FC<Props> = (props) => {
25
26
  if (showSearch || props.userChurches?.length === 0) return <SelectChurchSearch selectChurch={props.selectChurch} registeredChurchCallback={props.registeredChurchCallback} appName={props.appName} />
26
27
  else return (<>
27
28
  {props.userChurches?.map(uc => (<SelectableChurch church={uc.church} selectChurch={props.selectChurch} key={uc.church.id} />))}
28
- <a href="about:blank" style={{ display: "block", textAlign: "center" }} onClick={(e) => { e.preventDefault(); setShowSearch(true); }}>Choose another church</a>
29
+ <a href="about:blank" style={{ display: "block", textAlign: "center" }} onClick={(e) => { e.preventDefault(); setShowSearch(true); }}>{Locale.label("selectChurch.another")}</a>
29
30
  </>);
30
31
  }
31
32
 
32
33
  return (
33
34
  <Dialog open={props.show} onClose={handleClose}>
34
- <DialogTitle>Select Church</DialogTitle>
35
+ <DialogTitle>{Locale.label("selectChurch.selectChurch")}
36
+ </DialogTitle>
35
37
  <Tooltip title="Logout" arrow>
36
38
  <IconButton sx={{ position: "absolute", right: 8, top: 8 }} color="error" onClick={() => { window.location.href = "/logout" }}>
37
39
  <Icon>logout</Icon>
@@ -1,8 +1,8 @@
1
1
  import React from "react";
2
- import { ApiHelper } from "../../helpers"
2
+ import { ApiHelper, Locale } from "../../helpers"
3
3
  import { ChurchInterface, RegisterChurchRequestInterface } from "@churchapps/helpers";
4
4
  import { ErrorMessages, InputBox } from "../../components"
5
- import { Grid, InputAdornment, TextField } from "@mui/material";
5
+ import { Grid, TextField } from "@mui/material";
6
6
 
7
7
  interface Props {
8
8
  initialChurchName: string,
@@ -38,13 +38,12 @@ export const SelectChurchRegister: React.FC<Props> = (props) => {
38
38
 
39
39
  const validate = () => {
40
40
  let errors = [];
41
- if (!church.name?.trim()) errors.push("Church name cannot be blank.");
42
- //if (!church.subDomain?.trim()) errors.push("Subdomain cannot be blank.");
43
- if (!church.address1?.trim()) errors.push("Address cannot be blank.");
44
- if (!church.city?.trim()) errors.push("City cannot be blank.");
45
- if (!church.state?.trim()) errors.push("State/Province cannot be blank.");
46
- if (!church.zip?.trim()) errors.push("Zip/Postal cannot be blank.");
47
- if (!church.country?.trim()) errors.push("Country cannot be blank.");
41
+ if (!church.name?.trim()) errors.push(Locale.label("selectChurch.validate.name"));
42
+ if (!church.address1?.trim()) errors.push(Locale.label("selectChurch.validate.address"));
43
+ if (!church.city?.trim()) errors.push(Locale.label("selectChurch.validate.city"));
44
+ if (!church.state?.trim()) errors.push(Locale.label("selectChurch.validate.state"));
45
+ if (!church.zip?.trim()) errors.push(Locale.label("selectChurch.validate.zip"));
46
+ if (!church.country?.trim()) errors.push(Locale.label("selectChurch.validate.country"));
48
47
  setErrors(errors);
49
48
  return errors.length === 0;
50
49
  }
@@ -65,25 +64,21 @@ export const SelectChurchRegister: React.FC<Props> = (props) => {
65
64
  }
66
65
  }
67
66
 
68
- /*<TextField required fullWidth name="subDomain" label="Subdomain" id="subDomain" InputProps={{
69
- endAdornment: <InputAdornment position="end">.churchapps.org</InputAdornment>
70
- }} value={church.subDomain} onChange={handleChange} />
71
- */
72
67
  return (
73
- <InputBox id="churchBox" saveFunction={handleSave} headerText="Register a New Church" headerIcon="church" isSubmitting={isSubmitting}>
68
+ <InputBox id="churchBox" saveFunction={handleSave} headerText={Locale.label("selectChurch.register")} headerIcon="church" isSubmitting={isSubmitting}>
74
69
  <ErrorMessages errors={errors} />
75
- <TextField required fullWidth name="churchName" label="Church Name" value={church.name} onChange={handleChange} />
70
+ <TextField required fullWidth name="churchName" label={Locale.label("selectChurch.name")} value={church.name} onChange={handleChange} />
76
71
 
77
- <TextField required fullWidth name="address1" label="Address Line 1" value={church.address1} onChange={handleChange} />
72
+ <TextField required fullWidth name="address1" label={Locale.label("selectChurch.address1")} value={church.address1} onChange={handleChange} />
78
73
  <Grid container spacing={3}>
79
- <Grid item xs={6}><TextField fullWidth name="address2" label="Address Line 2" value={church.address2} onChange={handleChange} /></Grid>
80
- <Grid item xs={6}><TextField required fullWidth name="city" label="City" value={church.city} onChange={handleChange} /></Grid>
74
+ <Grid item xs={6}><TextField fullWidth name="address2" label={Locale.label("selectChurch.address2")} value={church.address2} onChange={handleChange} /></Grid>
75
+ <Grid item xs={6}><TextField required fullWidth name="city" label={Locale.label("selectChurch.city")} value={church.city} onChange={handleChange} /></Grid>
81
76
  </Grid>
82
77
  <Grid container spacing={3}>
83
- <Grid item xs={6}><TextField required fullWidth name="state" label="State / Province" value={church.state} onChange={handleChange} /></Grid>
84
- <Grid item xs={6}><TextField required fullWidth name="zip" label="Zip / Postal" value={church.zip} onChange={handleChange} /></Grid>
78
+ <Grid item xs={6}><TextField required fullWidth name="state" label={Locale.label("selectChurch.state")} value={church.state} onChange={handleChange} /></Grid>
79
+ <Grid item xs={6}><TextField required fullWidth name="zip" label={Locale.label("selectChurch.zip")} value={church.zip} onChange={handleChange} /></Grid>
85
80
  </Grid>
86
- <TextField required fullWidth name="country" label="Country" value={church.country} onChange={handleChange} />
81
+ <TextField required fullWidth name="country" label={Locale.label("selectChurch.country")} value={church.country} onChange={handleChange} />
87
82
  </InputBox>
88
83
  );
89
84
  };
@@ -1,6 +1,6 @@
1
1
  import { Button, TextField } from "@mui/material";
2
2
  import React from "react";
3
- import { ApiHelper } from "../../helpers"
3
+ import { ApiHelper, Locale } from "../../helpers"
4
4
  import { ChurchInterface } from "@churchapps/helpers";
5
5
  import { SelectableChurch } from "./SelectableChurch";
6
6
  import { SelectChurchRegister } from "./SelectChurchRegister";
@@ -28,7 +28,7 @@ export const SelectChurchSearch: React.FC<Props> = (props) => {
28
28
 
29
29
  const handleRegisterClick = (e: React.MouseEvent) => {
30
30
  e.preventDefault();
31
- if (window.confirm("Are you sure you wish to register a new church?")) {
31
+ if (window.confirm(Locale.label("selectChurch.confirmRegister"))) {
32
32
  setShowRegister(true);
33
33
  }
34
34
  }
@@ -36,7 +36,7 @@ export const SelectChurchSearch: React.FC<Props> = (props) => {
36
36
  const getRegisterLink = () => (
37
37
  <div>
38
38
  <a style={{ display: "block", textAlign: "center" }} href="about:blank" onClick={handleRegisterClick}>
39
- Register a New Church
39
+ {Locale.label("selectChurch.register")}
40
40
  </a>
41
41
  </div>
42
42
  )
@@ -52,7 +52,7 @@ export const SelectChurchSearch: React.FC<Props> = (props) => {
52
52
 
53
53
  const getResults = () => {
54
54
  if (churches === null) return;
55
- else if (churches.length === 0) return <><p>No matches found</p>{getRegisterLink()}</>
55
+ else if (churches.length === 0) return <><p>{Locale.label("selectChurch.noMatches")}</p>{getRegisterLink()}</>
56
56
  else return getChurches();
57
57
  }
58
58
 
@@ -60,7 +60,7 @@ export const SelectChurchSearch: React.FC<Props> = (props) => {
60
60
  else return (
61
61
  <>
62
62
  <TextField fullWidth name="searchText" label="Name" value={searchText} onChange={handleChange} onKeyDown={handleKeyDown}
63
- InputProps={{ endAdornment: <Button variant="contained" id="searchButton" data-cy="search-button" onClick={handleSubmit}>Search</Button> }}
63
+ InputProps={{ endAdornment: <Button variant="contained" id="searchButton" data-cy="search-button" onClick={handleSubmit}>{Locale.label("common.search")}</Button> }}
64
64
  />
65
65
  {getResults()}
66
66
  </>