@defra/forms-engine-plugin 4.22.0 → 5.0.0-alpha

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 (309) hide show
  1. package/.server/server/forms/register-as-a-unicorn-breeder.yaml +0 -14
  2. package/.server/server/forms/simple-form.yaml +106 -3
  3. package/.server/server/plugins/engine/components/AutocompleteField.d.ts +11 -11
  4. package/.server/server/plugins/engine/components/AutocompleteField.js +2 -2
  5. package/.server/server/plugins/engine/components/AutocompleteField.js.map +1 -1
  6. package/.server/server/plugins/engine/components/CheckboxesField.d.ts +3 -2
  7. package/.server/server/plugins/engine/components/CheckboxesField.js +4 -9
  8. package/.server/server/plugins/engine/components/CheckboxesField.js.map +1 -1
  9. package/.server/server/plugins/engine/components/ComponentCollection.d.ts +8 -7
  10. package/.server/server/plugins/engine/components/ComponentCollection.js +106 -51
  11. package/.server/server/plugins/engine/components/ComponentCollection.js.map +1 -1
  12. package/.server/server/plugins/engine/components/DatePartsField.d.ts +8 -6
  13. package/.server/server/plugins/engine/components/DatePartsField.js +27 -9
  14. package/.server/server/plugins/engine/components/DatePartsField.js.map +1 -1
  15. package/.server/server/plugins/engine/components/DeclarationField.d.ts +13 -11
  16. package/.server/server/plugins/engine/components/DeclarationField.js +31 -9
  17. package/.server/server/plugins/engine/components/DeclarationField.js.map +1 -1
  18. package/.server/server/plugins/engine/components/EastingNorthingField.d.ts +6 -5
  19. package/.server/server/plugins/engine/components/EastingNorthingField.js +42 -22
  20. package/.server/server/plugins/engine/components/EastingNorthingField.js.map +1 -1
  21. package/.server/server/plugins/engine/components/EmailAddressField.d.ts +11 -14
  22. package/.server/server/plugins/engine/components/EmailAddressField.js +2 -2
  23. package/.server/server/plugins/engine/components/EmailAddressField.js.map +1 -1
  24. package/.server/server/plugins/engine/components/FileUploadField.d.ts +14 -12
  25. package/.server/server/plugins/engine/components/FileUploadField.js +22 -12
  26. package/.server/server/plugins/engine/components/FileUploadField.js.map +1 -1
  27. package/.server/server/plugins/engine/components/FormComponent.d.ts +21 -12
  28. package/.server/server/plugins/engine/components/FormComponent.js +33 -14
  29. package/.server/server/plugins/engine/components/FormComponent.js.map +1 -1
  30. package/.server/server/plugins/engine/components/GeospatialField.d.ts +14 -12
  31. package/.server/server/plugins/engine/components/GeospatialField.js +19 -13
  32. package/.server/server/plugins/engine/components/GeospatialField.js.map +1 -1
  33. package/.server/server/plugins/engine/components/LatLongField.d.ts +6 -5
  34. package/.server/server/plugins/engine/components/LatLongField.js +32 -20
  35. package/.server/server/plugins/engine/components/LatLongField.js.map +1 -1
  36. package/.server/server/plugins/engine/components/ListFormComponent.d.ts +7 -6
  37. package/.server/server/plugins/engine/components/ListFormComponent.js +19 -7
  38. package/.server/server/plugins/engine/components/ListFormComponent.js.map +1 -1
  39. package/.server/server/plugins/engine/components/LocationFieldBase.d.ts +17 -16
  40. package/.server/server/plugins/engine/components/LocationFieldBase.js +2 -2
  41. package/.server/server/plugins/engine/components/LocationFieldBase.js.map +1 -1
  42. package/.server/server/plugins/engine/components/LocationFieldHelpers.d.ts +3 -3
  43. package/.server/server/plugins/engine/components/LocationFieldHelpers.js +2 -2
  44. package/.server/server/plugins/engine/components/LocationFieldHelpers.js.map +1 -1
  45. package/.server/server/plugins/engine/components/Markdown.d.ts +8 -7
  46. package/.server/server/plugins/engine/components/Markdown.js +5 -2
  47. package/.server/server/plugins/engine/components/Markdown.js.map +1 -1
  48. package/.server/server/plugins/engine/components/MonthYearField.d.ts +9 -7
  49. package/.server/server/plugins/engine/components/MonthYearField.js +26 -8
  50. package/.server/server/plugins/engine/components/MonthYearField.js.map +1 -1
  51. package/.server/server/plugins/engine/components/MultilineTextField.d.ts +10 -9
  52. package/.server/server/plugins/engine/components/MultilineTextField.js +2 -2
  53. package/.server/server/plugins/engine/components/MultilineTextField.js.map +1 -1
  54. package/.server/server/plugins/engine/components/NationalGridFieldNumberField.d.ts +2 -1
  55. package/.server/server/plugins/engine/components/NationalGridFieldNumberField.js +14 -6
  56. package/.server/server/plugins/engine/components/NationalGridFieldNumberField.js.map +1 -1
  57. package/.server/server/plugins/engine/components/NumberField.d.ts +10 -9
  58. package/.server/server/plugins/engine/components/NumberField.js +2 -2
  59. package/.server/server/plugins/engine/components/NumberField.js.map +1 -1
  60. package/.server/server/plugins/engine/components/OsGridRefField.d.ts +2 -1
  61. package/.server/server/plugins/engine/components/OsGridRefField.js +14 -6
  62. package/.server/server/plugins/engine/components/OsGridRefField.js.map +1 -1
  63. package/.server/server/plugins/engine/components/PaymentField.d.ts +12 -10
  64. package/.server/server/plugins/engine/components/PaymentField.js +21 -8
  65. package/.server/server/plugins/engine/components/PaymentField.js.map +1 -1
  66. package/.server/server/plugins/engine/components/SelectField.d.ts +11 -11
  67. package/.server/server/plugins/engine/components/SelectField.js +2 -2
  68. package/.server/server/plugins/engine/components/SelectField.js.map +1 -1
  69. package/.server/server/plugins/engine/components/SelectionControlField.d.ts +4 -4
  70. package/.server/server/plugins/engine/components/SelectionControlField.js +2 -2
  71. package/.server/server/plugins/engine/components/SelectionControlField.js.map +1 -1
  72. package/.server/server/plugins/engine/components/TelephoneNumberField.d.ts +10 -9
  73. package/.server/server/plugins/engine/components/TelephoneNumberField.js +2 -2
  74. package/.server/server/plugins/engine/components/TelephoneNumberField.js.map +1 -1
  75. package/.server/server/plugins/engine/components/UkAddressField.d.ts +12 -10
  76. package/.server/server/plugins/engine/components/UkAddressField.js +29 -17
  77. package/.server/server/plugins/engine/components/UkAddressField.js.map +1 -1
  78. package/.server/server/plugins/engine/components/YesNoField.d.ts +3 -0
  79. package/.server/server/plugins/engine/components/YesNoField.js +9 -0
  80. package/.server/server/plugins/engine/components/YesNoField.js.map +1 -1
  81. package/.server/server/plugins/engine/components/helpers/components.d.ts +3 -2
  82. package/.server/server/plugins/engine/components/helpers/components.js +11 -8
  83. package/.server/server/plugins/engine/components/helpers/components.js.map +1 -1
  84. package/.server/server/plugins/engine/components/types.d.ts +8 -1
  85. package/.server/server/plugins/engine/components/types.js.map +1 -1
  86. package/.server/server/plugins/engine/configureEnginePlugin.js +8 -1
  87. package/.server/server/plugins/engine/configureEnginePlugin.js.map +1 -1
  88. package/.server/server/plugins/engine/form-context.d.ts +1 -0
  89. package/.server/server/plugins/engine/form-context.js +4 -2
  90. package/.server/server/plugins/engine/form-context.js.map +1 -1
  91. package/.server/server/plugins/engine/helpers.d.ts +1 -1
  92. package/.server/server/plugins/engine/helpers.js +8 -13
  93. package/.server/server/plugins/engine/helpers.js.map +1 -1
  94. package/.server/server/plugins/engine/i18n/buildValidationMessages.d.ts +39 -0
  95. package/.server/server/plugins/engine/i18n/buildValidationMessages.js +50 -0
  96. package/.server/server/plugins/engine/i18n/buildValidationMessages.js.map +1 -0
  97. package/.server/server/plugins/engine/i18n/createFormTranslator.d.ts +5 -0
  98. package/.server/server/plugins/engine/i18n/createFormTranslator.js +18 -0
  99. package/.server/server/plugins/engine/i18n/createFormTranslator.js.map +1 -0
  100. package/.server/server/plugins/engine/i18n/createTranslator.d.ts +9 -0
  101. package/.server/server/plugins/engine/i18n/createTranslator.js +51 -0
  102. package/.server/server/plugins/engine/i18n/createTranslator.js.map +1 -0
  103. package/.server/server/plugins/engine/i18n/extractBaseTranslations.d.ts +5 -0
  104. package/.server/server/plugins/engine/i18n/extractBaseTranslations.js +57 -0
  105. package/.server/server/plugins/engine/i18n/extractBaseTranslations.js.map +1 -0
  106. package/.server/server/plugins/engine/i18n/index.d.ts +18 -0
  107. package/.server/server/plugins/engine/i18n/index.js +71 -0
  108. package/.server/server/plugins/engine/i18n/index.js.map +1 -0
  109. package/.server/server/plugins/engine/i18n/translations/cy.json +271 -0
  110. package/.server/server/plugins/engine/i18n/translations/en-GB.json +271 -0
  111. package/.server/server/plugins/engine/i18n/types.d.ts +41 -0
  112. package/.server/server/plugins/engine/i18n/types.js +2 -0
  113. package/.server/server/plugins/engine/i18n/types.js.map +1 -0
  114. package/.server/server/plugins/engine/index.js +3 -2
  115. package/.server/server/plugins/engine/index.js.map +1 -1
  116. package/.server/server/plugins/engine/models/FormModel.d.ts +9 -1
  117. package/.server/server/plugins/engine/models/FormModel.js +44 -18
  118. package/.server/server/plugins/engine/models/FormModel.js.map +1 -1
  119. package/.server/server/plugins/engine/models/SummaryViewModel.d.ts +5 -2
  120. package/.server/server/plugins/engine/models/SummaryViewModel.js +44 -18
  121. package/.server/server/plugins/engine/models/SummaryViewModel.js.map +1 -1
  122. package/.server/server/plugins/engine/options.js +2 -1
  123. package/.server/server/plugins/engine/options.js.map +1 -1
  124. package/.server/server/plugins/engine/outputFormatters/adapter/v1.js +4 -0
  125. package/.server/server/plugins/engine/outputFormatters/adapter/v1.js.map +1 -1
  126. package/.server/server/plugins/engine/outputFormatters/human/v1.js +2 -1
  127. package/.server/server/plugins/engine/outputFormatters/human/v1.js.map +1 -1
  128. package/.server/server/plugins/engine/outputFormatters/machine/v1.js +7 -6
  129. package/.server/server/plugins/engine/outputFormatters/machine/v1.js.map +1 -1
  130. package/.server/server/plugins/engine/pageControllers/FileUploadPageController.d.ts +2 -1
  131. package/.server/server/plugins/engine/pageControllers/FileUploadPageController.js +6 -3
  132. package/.server/server/plugins/engine/pageControllers/FileUploadPageController.js.map +1 -1
  133. package/.server/server/plugins/engine/pageControllers/PageController.d.ts +3 -1
  134. package/.server/server/plugins/engine/pageControllers/PageController.js +11 -1
  135. package/.server/server/plugins/engine/pageControllers/PageController.js.map +1 -1
  136. package/.server/server/plugins/engine/pageControllers/QuestionPageController.d.ts +4 -2
  137. package/.server/server/plugins/engine/pageControllers/QuestionPageController.js +52 -21
  138. package/.server/server/plugins/engine/pageControllers/QuestionPageController.js.map +1 -1
  139. package/.server/server/plugins/engine/pageControllers/RepeatPageController.d.ts +3 -2
  140. package/.server/server/plugins/engine/pageControllers/RepeatPageController.js +63 -26
  141. package/.server/server/plugins/engine/pageControllers/RepeatPageController.js.map +1 -1
  142. package/.server/server/plugins/engine/pageControllers/StartPageController.d.ts +3 -1
  143. package/.server/server/plugins/engine/pageControllers/StartPageController.js +2 -2
  144. package/.server/server/plugins/engine/pageControllers/StartPageController.js.map +1 -1
  145. package/.server/server/plugins/engine/pageControllers/StatusPageController.js +12 -2
  146. package/.server/server/plugins/engine/pageControllers/StatusPageController.js.map +1 -1
  147. package/.server/server/plugins/engine/pageControllers/SummaryPageController.d.ts +4 -3
  148. package/.server/server/plugins/engine/pageControllers/SummaryPageController.js +45 -28
  149. package/.server/server/plugins/engine/pageControllers/SummaryPageController.js.map +1 -1
  150. package/.server/server/plugins/engine/pageControllers/__stubs__/translator.d.ts +2 -0
  151. package/.server/server/plugins/engine/pageControllers/__stubs__/translator.js +24 -0
  152. package/.server/server/plugins/engine/pageControllers/__stubs__/translator.js.map +1 -0
  153. package/.server/server/plugins/engine/pageControllers/errors.d.ts +1 -1
  154. package/.server/server/plugins/engine/pageControllers/errors.js +3 -2
  155. package/.server/server/plugins/engine/pageControllers/errors.js.map +1 -1
  156. package/.server/server/plugins/engine/pageControllers/helpers/submission.d.ts +3 -2
  157. package/.server/server/plugins/engine/pageControllers/helpers/submission.js +4 -4
  158. package/.server/server/plugins/engine/pageControllers/helpers/submission.js.map +1 -1
  159. package/.server/server/plugins/engine/pageControllers/validationOptions.d.ts +7 -3
  160. package/.server/server/plugins/engine/pageControllers/validationOptions.js +34 -33
  161. package/.server/server/plugins/engine/pageControllers/validationOptions.js.map +1 -1
  162. package/.server/server/plugins/engine/plugin.js +2 -0
  163. package/.server/server/plugins/engine/plugin.js.map +1 -1
  164. package/.server/server/plugins/engine/routes/index.js +4 -1
  165. package/.server/server/plugins/engine/routes/index.js.map +1 -1
  166. package/.server/server/plugins/engine/routes/questions.js +5 -2
  167. package/.server/server/plugins/engine/routes/questions.js.map +1 -1
  168. package/.server/server/plugins/engine/types/index.d.ts +1 -0
  169. package/.server/server/plugins/engine/types/index.js.map +1 -1
  170. package/.server/server/plugins/engine/types/schema.js +1 -0
  171. package/.server/server/plugins/engine/types/schema.js.map +1 -1
  172. package/.server/server/plugins/engine/types.d.ts +12 -1
  173. package/.server/server/plugins/engine/types.js.map +1 -1
  174. package/.server/server/plugins/engine/views/components/_location-field-base.html +1 -1
  175. package/.server/server/plugins/engine/views/components/fileuploadfield.html +3 -3
  176. package/.server/server/plugins/engine/views/components/nationalgridfieldnumberfield.html +1 -1
  177. package/.server/server/plugins/engine/views/components/osgridreffield.html +1 -1
  178. package/.server/server/plugins/engine/views/components/paymentfield.html +8 -8
  179. package/.server/server/plugins/engine/views/components/ukaddressfield.html +4 -4
  180. package/.server/server/plugins/engine/views/confirmation.html +4 -4
  181. package/.server/server/plugins/engine/views/exit.html +4 -4
  182. package/.server/server/plugins/engine/views/file-upload.html +3 -3
  183. package/.server/server/plugins/engine/views/index.html +3 -3
  184. package/.server/server/plugins/engine/views/item-delete.html +1 -1
  185. package/.server/server/plugins/engine/views/partials/form.html +3 -3
  186. package/.server/server/plugins/engine/views/partials/preview-banner.html +4 -4
  187. package/.server/server/plugins/engine/views/partials/warn-missing-notification-email.html +4 -5
  188. package/.server/server/plugins/engine/views/repeat-list-summary.html +4 -4
  189. package/.server/server/plugins/engine/views/summary.html +14 -7
  190. package/.server/server/plugins/nunjucks/enviroment.test.js +10 -0
  191. package/.server/server/plugins/nunjucks/enviroment.test.js.map +1 -1
  192. package/.server/server/plugins/nunjucks/environment.d.ts +8 -0
  193. package/.server/server/plugins/nunjucks/environment.js +13 -0
  194. package/.server/server/plugins/nunjucks/environment.js.map +1 -1
  195. package/.server/server/plugins/nunjucks/filters/answer.js +9 -1
  196. package/.server/server/plugins/nunjucks/filters/answer.js.map +1 -1
  197. package/.server/server/plugins/nunjucks/filters/answer.test.js +13 -2
  198. package/.server/server/plugins/nunjucks/filters/answer.test.js.map +1 -1
  199. package/.server/server/plugins/nunjucks/filters/field.d.ts +1 -1
  200. package/.server/server/plugins/postcode-lookup/models/index.d.ts +24 -19
  201. package/.server/server/plugins/postcode-lookup/models/index.js +83 -76
  202. package/.server/server/plugins/postcode-lookup/models/index.js.map +1 -1
  203. package/.server/server/plugins/postcode-lookup/routes/index.js +7 -13
  204. package/.server/server/plugins/postcode-lookup/routes/index.js.map +1 -1
  205. package/.server/server/plugins/postcode-lookup/types.d.ts +1 -0
  206. package/.server/server/plugins/postcode-lookup/types.js +1 -0
  207. package/.server/server/plugins/postcode-lookup/types.js.map +1 -1
  208. package/.server/server/plugins/postcode-lookup/views/postcode-lookup-details.html +3 -3
  209. package/.server/server/types.d.ts +2 -1
  210. package/.server/server/types.js.map +1 -1
  211. package/.server/server/utils/utils.d.ts +5 -0
  212. package/.server/server/utils/utils.js +16 -0
  213. package/.server/server/utils/utils.js.map +1 -1
  214. package/.server/typings/hapi/index.d.js.map +1 -1
  215. package/package.json +3 -2
  216. package/src/server/forms/register-as-a-unicorn-breeder.yaml +0 -14
  217. package/src/server/forms/simple-form.yaml +106 -3
  218. package/src/server/plugins/engine/components/AutocompleteField.ts +3 -6
  219. package/src/server/plugins/engine/components/CheckboxesField.ts +12 -11
  220. package/src/server/plugins/engine/components/ComponentCollection.ts +143 -61
  221. package/src/server/plugins/engine/components/DatePartsField.ts +33 -11
  222. package/src/server/plugins/engine/components/DeclarationField.ts +37 -14
  223. package/src/server/plugins/engine/components/EastingNorthingField.ts +83 -22
  224. package/src/server/plugins/engine/components/EmailAddressField.ts +4 -7
  225. package/src/server/plugins/engine/components/FileUploadField.ts +28 -22
  226. package/src/server/plugins/engine/components/FormComponent.ts +49 -12
  227. package/src/server/plugins/engine/components/GeospatialField.ts +36 -21
  228. package/src/server/plugins/engine/components/LatLongField.ts +52 -21
  229. package/src/server/plugins/engine/components/ListFormComponent.ts +26 -10
  230. package/src/server/plugins/engine/components/LocationFieldBase.ts +5 -8
  231. package/src/server/plugins/engine/components/LocationFieldHelpers.ts +3 -3
  232. package/src/server/plugins/engine/components/Markdown.ts +7 -3
  233. package/src/server/plugins/engine/components/MonthYearField.ts +32 -10
  234. package/src/server/plugins/engine/components/MultilineTextField.ts +5 -8
  235. package/src/server/plugins/engine/components/NationalGridFieldNumberField.ts +25 -11
  236. package/src/server/plugins/engine/components/NumberField.ts +3 -4
  237. package/src/server/plugins/engine/components/OsGridRefField.ts +25 -9
  238. package/src/server/plugins/engine/components/PaymentField.ts +22 -12
  239. package/src/server/plugins/engine/components/SelectField.ts +3 -6
  240. package/src/server/plugins/engine/components/SelectionControlField.ts +7 -8
  241. package/src/server/plugins/engine/components/TelephoneNumberField.ts +4 -7
  242. package/src/server/plugins/engine/components/UkAddressField.ts +33 -18
  243. package/src/server/plugins/engine/components/YesNoField.ts +10 -0
  244. package/src/server/plugins/engine/components/helpers/components.ts +13 -6
  245. package/src/server/plugins/engine/components/types.ts +9 -0
  246. package/src/server/plugins/engine/configureEnginePlugin.ts +12 -1
  247. package/src/server/plugins/engine/form-context.ts +8 -2
  248. package/src/server/plugins/engine/helpers.ts +10 -18
  249. package/src/server/plugins/engine/i18n/buildValidationMessages.ts +69 -0
  250. package/src/server/plugins/engine/i18n/createFormTranslator.ts +33 -0
  251. package/src/server/plugins/engine/i18n/createTranslator.ts +61 -0
  252. package/src/server/plugins/engine/i18n/extractBaseTranslations.ts +61 -0
  253. package/src/server/plugins/engine/i18n/index.ts +80 -0
  254. package/src/server/plugins/engine/i18n/translations/cy.json +271 -0
  255. package/src/server/plugins/engine/i18n/translations/en-GB.json +271 -0
  256. package/src/server/plugins/engine/i18n/types.ts +62 -0
  257. package/src/server/plugins/engine/index.ts +4 -2
  258. package/src/server/plugins/engine/models/FormModel.ts +59 -23
  259. package/src/server/plugins/engine/models/SummaryViewModel.ts +68 -25
  260. package/src/server/plugins/engine/options.js +2 -1
  261. package/src/server/plugins/engine/outputFormatters/adapter/v1.ts +5 -0
  262. package/src/server/plugins/engine/outputFormatters/human/v1.ts +2 -3
  263. package/src/server/plugins/engine/outputFormatters/machine/v1.ts +9 -8
  264. package/src/server/plugins/engine/pageControllers/FileUploadPageController.ts +7 -3
  265. package/src/server/plugins/engine/pageControllers/PageController.ts +12 -1
  266. package/src/server/plugins/engine/pageControllers/QuestionPageController.ts +53 -21
  267. package/src/server/plugins/engine/pageControllers/RepeatPageController.ts +66 -29
  268. package/src/server/plugins/engine/pageControllers/StartPageController.ts +7 -2
  269. package/src/server/plugins/engine/pageControllers/StatusPageController.ts +10 -2
  270. package/src/server/plugins/engine/pageControllers/SummaryPageController.ts +53 -24
  271. package/src/server/plugins/engine/pageControllers/__stubs__/translator.ts +28 -0
  272. package/src/server/plugins/engine/pageControllers/errors.ts +4 -2
  273. package/src/server/plugins/engine/pageControllers/helpers/submission.ts +11 -4
  274. package/src/server/plugins/engine/pageControllers/validationOptions.ts +43 -53
  275. package/src/server/plugins/engine/plugin.ts +2 -0
  276. package/src/server/plugins/engine/routes/index.ts +9 -1
  277. package/src/server/plugins/engine/routes/questions.ts +5 -1
  278. package/src/server/plugins/engine/types/index.ts +5 -0
  279. package/src/server/plugins/engine/types/schema.ts +1 -0
  280. package/src/server/plugins/engine/types.ts +10 -0
  281. package/src/server/plugins/engine/views/components/_location-field-base.html +1 -1
  282. package/src/server/plugins/engine/views/components/fileuploadfield.html +3 -3
  283. package/src/server/plugins/engine/views/components/nationalgridfieldnumberfield.html +1 -1
  284. package/src/server/plugins/engine/views/components/osgridreffield.html +1 -1
  285. package/src/server/plugins/engine/views/components/paymentfield.html +8 -8
  286. package/src/server/plugins/engine/views/components/ukaddressfield.html +4 -4
  287. package/src/server/plugins/engine/views/confirmation.html +4 -4
  288. package/src/server/plugins/engine/views/exit.html +4 -4
  289. package/src/server/plugins/engine/views/file-upload.html +3 -3
  290. package/src/server/plugins/engine/views/index.html +3 -3
  291. package/src/server/plugins/engine/views/item-delete.html +1 -1
  292. package/src/server/plugins/engine/views/partials/form.html +3 -3
  293. package/src/server/plugins/engine/views/partials/preview-banner.html +4 -4
  294. package/src/server/plugins/engine/views/partials/warn-missing-notification-email.html +4 -5
  295. package/src/server/plugins/engine/views/repeat-list-summary.html +4 -4
  296. package/src/server/plugins/engine/views/summary.html +14 -7
  297. package/src/server/plugins/nunjucks/environment.js +14 -0
  298. package/src/server/plugins/nunjucks/filters/answer.js +12 -1
  299. package/src/server/plugins/postcode-lookup/models/index.js +144 -87
  300. package/src/server/plugins/postcode-lookup/routes/index.js +13 -16
  301. package/src/server/plugins/postcode-lookup/types.js +1 -0
  302. package/src/server/plugins/postcode-lookup/views/postcode-lookup-details.html +3 -3
  303. package/src/server/types.ts +2 -0
  304. package/src/server/utils/utils.js +14 -0
  305. package/src/typings/hapi/index.d.ts +1 -0
  306. package/.server/server/plugins/engine/components/constants.d.ts +0 -1
  307. package/.server/server/plugins/engine/components/constants.js +0 -2
  308. package/.server/server/plugins/engine/components/constants.js.map +0 -1
  309. package/src/server/plugins/engine/components/constants.ts +0 -1
@@ -2,12 +2,14 @@ import {
2
2
  ComponentType,
3
3
  hasFormComponents,
4
4
  isFormType,
5
+ type ComponentDef,
5
6
  type DeclarationFieldComponent,
6
7
  type Item
7
8
  } from '@defra/forms-model'
8
9
  import joi, {
9
10
  type ArraySchema,
10
11
  type BooleanSchema,
12
+ type LanguageMessages,
11
13
  type StringSchema
12
14
  } from 'joi'
13
15
 
@@ -15,23 +17,23 @@ import {
15
17
  FormComponent,
16
18
  isFormValue
17
19
  } from './FormComponent.js'
20
+ import { type RenderContext } from './types.js'
21
+ import { buildValidationMessages } from '../i18n/buildValidationMessages.js'
22
+ import { type Translator } from '../i18n/types.js'
18
23
  import { messageTemplate } from '../pageControllers/validationOptions.js'
19
24
  import {
20
25
  type ErrorMessageTemplateList,
21
26
  type FormPayload,
22
27
  type FormState,
23
28
  type FormStateValue,
24
- type FormSubmissionError,
25
29
  type FormSubmissionState,
26
30
  type FormValue
27
31
  } from '../types.js'
28
32
 
29
33
  export class DeclarationField extends FormComponent {
30
- private readonly DEFAULT_DECLARATION_LABEL = 'I understand and agree'
31
-
32
34
  declare options: DeclarationFieldComponent['options']
33
35
 
34
- declare declarationConfirmationLabel: string
36
+ declare declarationConfirmationLabel: string | undefined
35
37
 
36
38
  declare formSchema: ArraySchema<StringSchema[]>
37
39
  declare stateSchema: BooleanSchema
@@ -69,8 +71,9 @@ export class DeclarationField extends FormComponent {
69
71
 
70
72
  this.options = options
71
73
  this.content = content
72
- this.declarationConfirmationLabel =
73
- options.declarationConfirmationLabel ?? this.DEFAULT_DECLARATION_LABEL
74
+ // Store only the form-authored label (if provided). If absent, getViewModel
75
+ // resolves the default via t() at render time so the correct language is used.
76
+ this.declarationConfirmationLabel = options.declarationConfirmationLabel
74
77
  const formComponents = hasFormComponents(props.page?.pageDef)
75
78
  ? props.page.pageDef.components
76
79
  : []
@@ -114,20 +117,40 @@ export class DeclarationField extends FormComponent {
114
117
  return this.isValue(value) ? value : undefined
115
118
  }
116
119
 
117
- getDisplayStringFromFormValue(value: FormValue | FormPayload): string {
118
- return value === 'true' ? this.declarationConfirmationLabel : 'Not provided'
120
+ getValidationMessagesOverride(translator: Translator) {
121
+ const { declarationRequired } = buildValidationMessages(translator.t)
122
+ const msg = declarationRequired as unknown as string
123
+ return {
124
+ 'any.required': msg,
125
+ 'any.unknown': msg,
126
+ 'array.includesRequiredUnknowns': msg
127
+ } as unknown as LanguageMessages
119
128
  }
120
129
 
121
- getViewModel(payload: FormPayload, errors?: FormSubmissionError[]) {
122
- const defaultDeclarationConfirmationLabel =
123
- 'I confirm that I understand and accept this declaration'
130
+ getDisplayStringFromFormValue(
131
+ value: FormValue | FormPayload,
132
+ translator: Translator
133
+ ): string {
134
+ const { t } = translator
135
+ return value === 'true'
136
+ ? (this.declarationConfirmationLabel ??
137
+ t('components.declarationField.defaultLabel'))
138
+ : t('components.declarationField.notProvided')
139
+ }
140
+
141
+ getViewModel(context: RenderContext) {
142
+ const { payload } = context
143
+ const { t, tComponent } = context.translator
144
+
124
145
  const {
125
146
  hint,
126
- content,
127
- declarationConfirmationLabel = defaultDeclarationConfirmationLabel
147
+ declarationConfirmationLabel = t(
148
+ 'components.declarationField.defaultLabel'
149
+ )
128
150
  } = this
151
+ const content = tComponent(this as unknown as ComponentDef, 'content')
129
152
 
130
- const viewModel = super.getViewModel(payload, errors)
153
+ const viewModel = super.getViewModel(context)
131
154
  let { fieldset, label } = viewModel
132
155
 
133
156
  fieldset ??= {
@@ -16,7 +16,12 @@ import {
16
16
  } from './LocationFieldHelpers.js'
17
17
  import { NumberField } from './NumberField.js'
18
18
  import { createLowerFirstExpression } from './helpers/index.js'
19
- import { type EastingNorthingState } from './types.js'
19
+ import {
20
+ type EastingNorthingState,
21
+ type RenderContext
22
+ } from './types.js'
23
+ import { t as tPlugin } from '../i18n/index.js'
24
+ import { type Translator } from '../i18n/types.js'
20
25
  import { messageTemplate } from '../pageControllers/validationOptions.js'
21
26
  import {
22
27
  type ErrorMessageTemplateList,
@@ -55,18 +60,47 @@ export class EastingNorthingField extends FormComponent {
55
60
  const northingMin = schema?.northing?.min ?? DEFAULT_NORTHING_MIN
56
61
  const northingMax = schema?.northing?.max ?? DEFAULT_NORTHING_MAX
57
62
 
58
- const eastingRequired = 'Enter easting'
59
- const northingRequired = 'Enter northing'
63
+ const fieldLabel = lowerFirst(this.label)
60
64
 
61
- const eastingDigitsMessage = `{{#label}} for ${lowerFirst(this.label)} must be between 1 and 6 digits`
62
- const northingDigitsMessage = `{{#label}} for ${lowerFirst(this.label)} must be between 1 and 7 digits`
65
+ const eastingDigitsMessage = tPlugin(
66
+ 'components.eastingNorthingField.eastingDigits',
67
+ 'en-GB',
68
+ { fieldLabel }
69
+ )
70
+ const northingDigitsMessage = tPlugin(
71
+ 'components.eastingNorthingField.northingDigits',
72
+ 'en-GB',
73
+ { fieldLabel }
74
+ )
63
75
 
64
76
  const customValidationMessages: LanguageMessages =
65
77
  convertToLanguageMessages({
66
- 'any.required': eastingRequired,
67
- 'number.base': eastingRequired,
68
- 'number.min': `{{#label}} for ${lowerFirst(this.label)} must be between {{#limit}} and ${eastingMax}`,
69
- 'number.max': `{{#label}} for ${lowerFirst(this.label)} must be between ${eastingMin} and {{#limit}}`,
78
+ 'any.required': tPlugin(
79
+ 'components.eastingNorthingField.eastingRequired',
80
+ 'en-GB'
81
+ ),
82
+ 'number.base': tPlugin(
83
+ 'components.eastingNorthingField.eastingRequired',
84
+ 'en-GB'
85
+ ),
86
+ 'number.min': tPlugin(
87
+ 'components.eastingNorthingField.eastingRange',
88
+ 'en-GB',
89
+ {
90
+ fieldLabel,
91
+ min: eastingMin,
92
+ max: eastingMax
93
+ }
94
+ ),
95
+ 'number.max': tPlugin(
96
+ 'components.eastingNorthingField.eastingRange',
97
+ 'en-GB',
98
+ {
99
+ fieldLabel,
100
+ min: eastingMin,
101
+ max: eastingMax
102
+ }
103
+ ),
70
104
  'number.precision': eastingDigitsMessage,
71
105
  'number.integer': eastingDigitsMessage,
72
106
  'number.unsafe': eastingDigitsMessage
@@ -74,10 +108,32 @@ export class EastingNorthingField extends FormComponent {
74
108
 
75
109
  const northingValidationMessages: LanguageMessages =
76
110
  convertToLanguageMessages({
77
- 'any.required': northingRequired,
78
- 'number.base': northingRequired,
79
- 'number.min': `{{#label}} for ${lowerFirst(this.label)} must be between {{#limit}} and ${northingMax}`,
80
- 'number.max': `{{#label}} for ${lowerFirst(this.label)} must be between ${northingMin} and {{#limit}}`,
111
+ 'any.required': tPlugin(
112
+ 'components.eastingNorthingField.northingRequired',
113
+ 'en-GB'
114
+ ),
115
+ 'number.base': tPlugin(
116
+ 'components.eastingNorthingField.northingRequired',
117
+ 'en-GB'
118
+ ),
119
+ 'number.min': tPlugin(
120
+ 'components.eastingNorthingField.northingRange',
121
+ 'en-GB',
122
+ {
123
+ fieldLabel,
124
+ min: northingMin,
125
+ max: northingMax
126
+ }
127
+ ),
128
+ 'number.max': tPlugin(
129
+ 'components.eastingNorthingField.northingRange',
130
+ 'en-GB',
131
+ {
132
+ fieldLabel,
133
+ min: northingMin,
134
+ max: northingMax
135
+ }
136
+ ),
81
137
  'number.precision': northingDigitsMessage,
82
138
  'number.integer': northingDigitsMessage,
83
139
  'number.unsafe': northingDigitsMessage
@@ -88,7 +144,7 @@ export class EastingNorthingField extends FormComponent {
88
144
  {
89
145
  type: ComponentType.NumberField,
90
146
  name: `${name}__easting`,
91
- title: 'Easting',
147
+ title: 'components.eastingNorthingField.easting',
92
148
  schema: {
93
149
  min: eastingMin,
94
150
  max: eastingMax,
@@ -104,7 +160,7 @@ export class EastingNorthingField extends FormComponent {
104
160
  {
105
161
  type: ComponentType.NumberField,
106
162
  name: `${name}__northing`,
107
- title: 'Northing',
163
+ title: 'components.eastingNorthingField.northing',
108
164
  schema: {
109
165
  min: northingMin,
110
166
  max: northingMax,
@@ -135,7 +191,8 @@ export class EastingNorthingField extends FormComponent {
135
191
  }
136
192
 
137
193
  getDisplayStringFromFormValue(
138
- value: EastingNorthingState | undefined
194
+ value: EastingNorthingState | undefined,
195
+ _translator: Translator
139
196
  ): string {
140
197
  if (!value) {
141
198
  return ''
@@ -145,10 +202,13 @@ export class EastingNorthingField extends FormComponent {
145
202
  return `${value.easting}, ${value.northing}`
146
203
  }
147
204
 
148
- getDisplayStringFromState(state: FormSubmissionState) {
205
+ getDisplayStringFromState(
206
+ state: FormSubmissionState,
207
+ translator: Translator
208
+ ) {
149
209
  const value = this.getFormValueFromState(state)
150
210
 
151
- return this.getDisplayStringFromFormValue(value)
211
+ return this.getDisplayStringFromFormValue(value, translator)
152
212
  }
153
213
 
154
214
  getContextValueFromFormValue(
@@ -167,15 +227,16 @@ export class EastingNorthingField extends FormComponent {
167
227
  return this.getContextValueFromFormValue(value)
168
228
  }
169
229
 
170
- getViewModel(payload: FormPayload, errors?: FormSubmissionError[]) {
171
- const viewModel = super.getViewModel(payload, errors)
172
- return getLocationFieldViewModel(this, viewModel, payload, errors)
230
+ getViewModel(context: RenderContext) {
231
+ const viewModel = super.getViewModel(context)
232
+ return getLocationFieldViewModel(this, viewModel, context)
173
233
  }
174
234
 
175
235
  getViewErrors(
236
+ translator: Translator,
176
237
  errors?: FormSubmissionError[]
177
238
  ): FormSubmissionError[] | undefined {
178
- const allErrors = this.getErrors(errors)
239
+ const allErrors = this.getErrors(translator, errors)
179
240
  return deduplicateErrorsByHref(allErrors)
180
241
  }
181
242
 
@@ -5,12 +5,9 @@ import {
5
5
  import joi, { type CustomHelpers } from 'joi'
6
6
 
7
7
  import { FormComponent } from './FormComponent.js'
8
+ import { type RenderContext } from './types.js'
8
9
  import { messageTemplate } from '../pageControllers/validationOptions.js'
9
- import {
10
- type ErrorMessageTemplateList,
11
- type FormPayload,
12
- type FormSubmissionError
13
- } from '../types.js'
10
+ import { type ErrorMessageTemplateList } from '../types.js'
14
11
 
15
12
  export class EmailAddressField extends FormComponent {
16
13
  declare options: EmailAddressFieldComponent['options']
@@ -54,8 +51,8 @@ export class EmailAddressField extends FormComponent {
54
51
  this.options = options
55
52
  }
56
53
 
57
- getViewModel(payload: FormPayload, errors?: FormSubmissionError[]) {
58
- const viewModel = super.getViewModel(payload, errors)
54
+ getViewModel(context: RenderContext) {
55
+ const viewModel = super.getViewModel(context)
59
56
  const { attributes } = viewModel
60
57
 
61
58
  attributes.autocomplete = 'email'
@@ -9,6 +9,8 @@ import {
9
9
  FormComponent,
10
10
  isUploadState
11
11
  } from './FormComponent.js'
12
+ import { type RenderContext } from './types.js'
13
+ import { type Translator } from '../i18n/types.js'
12
14
  import { InvalidComponentStateError } from '../pageControllers/errors.js'
13
15
  import { messageTemplate } from '../pageControllers/validationOptions.js'
14
16
  import {
@@ -19,10 +21,8 @@ import {
19
21
  type FileUpload,
20
22
  type FileUploadMetadata,
21
23
  type FormContext,
22
- type FormPayload,
23
24
  type FormState,
24
25
  type FormStateValue,
25
- type FormSubmissionError,
26
26
  type FormSubmissionState,
27
27
  type SummaryList,
28
28
  type SummaryListAction,
@@ -32,10 +32,8 @@ import {
32
32
  type UploadStatusResponse
33
33
  } from '../types.js'
34
34
  import { render } from '../../nunjucks/index.js'
35
- import {
36
- type FormQuery,
37
- type FormRequestPayload
38
- } from '../../../routes/types.js'
35
+ import { type FormRequestPayload } from '../../../routes/types.js'
36
+ import { resolveLanguage } from '../../../utils/utils.js'
39
37
 
40
38
  export const uploadIdSchema = joi.string().uuid().required()
41
39
 
@@ -163,19 +161,26 @@ export class FileUploadField extends FormComponent {
163
161
  return this.isValue(value) ? value : undefined
164
162
  }
165
163
 
166
- getDisplayStringFromFormValue(files: FileState[] | undefined): string {
164
+ getDisplayStringFromFormValue(
165
+ files: FileState[] | undefined,
166
+ translator: Translator
167
+ ): string {
167
168
  if (!files?.length) {
168
169
  return ''
169
170
  }
170
171
 
171
- const unit = files.length === 1 ? 'file' : 'files'
172
- return `Uploaded ${files.length} ${unit}`
172
+ return translator.t('components.fileUploadField.filesCount', {
173
+ count: files.length
174
+ })
173
175
  }
174
176
 
175
- getDisplayStringFromState(state: FormSubmissionState) {
177
+ getDisplayStringFromState(
178
+ state: FormSubmissionState,
179
+ translator: Translator
180
+ ) {
176
181
  const files = this.getFormValueFromState(state)
177
182
 
178
- return this.getDisplayStringFromFormValue(files)
183
+ return this.getDisplayStringFromFormValue(files, translator)
179
184
  }
180
185
 
181
186
  getContextValueFromFormValue(
@@ -189,17 +194,12 @@ export class FileUploadField extends FormComponent {
189
194
  return this.getContextValueFromFormValue(files)
190
195
  }
191
196
 
192
- getViewModel(
193
- payload: FormPayload,
194
- errors?: FormSubmissionError[],
195
- query: FormQuery = {}
196
- ) {
197
+ getViewModel(context: RenderContext) {
198
+ const { errors, isForceAccess = false } = context
199
+ const { t } = context.translator
197
200
  const { options, page, schema } = this
198
201
 
199
- // Allow preview URL direct access
200
- const isForceAccess = 'force' in query
201
-
202
- const viewModel = super.getViewModel(payload, errors)
202
+ const viewModel = super.getViewModel(context)
203
203
  const { attributes, id, value } = viewModel
204
204
 
205
205
  const files = this.getFormValue(value) ?? []
@@ -213,7 +213,10 @@ export class FileUploadField extends FormComponent {
213
213
  const { form } = status
214
214
  const { file } = form
215
215
 
216
- const tag = { classes: 'govuk-tag--green', text: 'Uploaded' }
216
+ const tag = {
217
+ classes: 'govuk-tag--green',
218
+ text: t('components.fileUploadField.uploaded')
219
+ }
217
220
 
218
221
  const valueHtml = render
219
222
  .view('components/fileuploadfield-value.html', {
@@ -309,6 +312,9 @@ export class FileUploadField extends FormComponent {
309
312
  metadata: FormMetadata,
310
313
  context: FormContext
311
314
  ) {
315
+ const language = resolveLanguage(request)
316
+ const { t } = this.model.createTranslator(language)
317
+
312
318
  const notificationEmail = metadata.notificationEmail
313
319
 
314
320
  if (!notificationEmail) {
@@ -347,7 +353,7 @@ export class FileUploadField extends FormComponent {
347
353
  // Scenarios: file missing from S3, invalid retrieval key (timing problem), etc.
348
354
  throw new InvalidComponentStateError(
349
355
  this,
350
- 'There was a problem with your uploaded files. Re-upload them before submitting the form again.'
356
+ t('components.fileUploadField.uploadFailed')
351
357
  )
352
358
  }
353
359
 
@@ -1,11 +1,14 @@
1
1
  import {
2
+ type ComponentDef,
2
3
  type FormComponentsDef,
3
4
  type FormMetadata,
4
5
  type Item
5
6
  } from '@defra/forms-model'
7
+ import { type LanguageMessages } from 'joi'
6
8
 
7
9
  import { ComponentBase } from './ComponentBase.js'
8
- import { optionalText } from './constants.js'
10
+ import { type RenderContext } from './types.js'
11
+ import { type Translator } from '../i18n/types.js'
9
12
  import {
10
13
  type FormContext,
11
14
  type FormRequestPayload
@@ -115,7 +118,10 @@ export class FormComponent extends ComponentBase {
115
118
  }
116
119
  }
117
120
 
118
- getErrors(errors?: FormSubmissionError[]): FormSubmissionError[] | undefined {
121
+ getErrors(
122
+ _translator: Translator,
123
+ errors?: FormSubmissionError[]
124
+ ): FormSubmissionError[] | undefined {
119
125
  const { name } = this
120
126
 
121
127
  // Filter component and child errors only
@@ -134,34 +140,59 @@ export class FormComponent extends ComponentBase {
134
140
  }
135
141
 
136
142
  getFirstError(
143
+ translator: Translator,
137
144
  errors?: FormSubmissionError[]
138
145
  ): FormSubmissionError | undefined {
139
- return this.getErrors(errors)?.[0]
146
+ return this.getErrors(translator, errors)?.[0]
140
147
  }
141
148
 
142
149
  getViewErrors(
150
+ translator: Translator,
143
151
  errors?: FormSubmissionError[]
144
152
  ): FormSubmissionError[] | undefined {
145
- const firstError = this.getFirstError(errors)
153
+ const firstError = this.getFirstError(translator, errors)
146
154
  return firstError && [firstError]
147
155
  }
148
156
 
149
- getViewModel(payload: FormPayload, errors?: FormSubmissionError[]) {
157
+ /**
158
+ * Override in composite fields to return translated Joi message overrides for
159
+ * their sub-fields, applied at validation time so schema-level English messages
160
+ * are replaced with the correct language. Return null to skip message patching.
161
+ */
162
+ getValidationMessagesOverride(
163
+ _translator: Translator
164
+ ): LanguageMessages | null {
165
+ return null
166
+ }
167
+
168
+ getViewModel({
169
+ payload,
170
+ errors,
171
+ translator,
172
+ isForceAccess: _isForceAccess = false
173
+ }: RenderContext) {
150
174
  const { hint, name, options = {}, title, viewModel } = this
151
175
 
176
+ const { t, tComponent } = translator
177
+
152
178
  const isRequired = !('required' in options) || options.required !== false
153
179
  const hideOptional = 'optionalText' in options && options.optionalText
154
- const label = `${title}${!isRequired && !hideOptional ? optionalText : ''}`
180
+
181
+ const resolvedTitle =
182
+ tComponent(this as unknown as ComponentDef, 'title') || title
183
+ const optionalTag =
184
+ !isRequired && !hideOptional ? ` ${t('common.optional')}` : ''
185
+ const label = `${resolvedTitle}${optionalTag}`
155
186
 
156
187
  if (hint) {
157
188
  viewModel.hint = {
158
- text: hint
189
+ text: tComponent(this as unknown as ComponentDef, 'hint') || hint
159
190
  }
160
191
  }
161
192
 
162
193
  // Filter component errors only
163
- const componentErrors = this.getErrors(errors)
164
- const componentError = this.getFirstError(componentErrors)
194
+ const componentErrors = this.getErrors(translator, errors)
195
+ const componentError = this.getFirstError(translator, componentErrors)
165
196
 
166
197
  if (componentErrors) {
167
198
  viewModel.errors = componentErrors
@@ -184,15 +215,21 @@ export class FormComponent extends ComponentBase {
184
215
  }
185
216
  }
186
217
 
187
- getDisplayStringFromFormValue(value: FormValue | FormPayload): string {
218
+ getDisplayStringFromFormValue(
219
+ value: FormValue | FormPayload,
220
+ _translator: Translator
221
+ ): string {
188
222
  // Map selected values to text
189
223
  // eslint-disable-next-line @typescript-eslint/no-base-to-string
190
224
  return this.isValue(value) ? value.toString() : ''
191
225
  }
192
226
 
193
- getDisplayStringFromState(state: FormSubmissionState): string {
227
+ getDisplayStringFromState(
228
+ state: FormSubmissionState,
229
+ translator: Translator
230
+ ): string {
194
231
  const value = this.getFormValueFromState(state)
195
- return this.getDisplayStringFromFormValue(value)
232
+ return this.getDisplayStringFromFormValue(value, translator)
196
233
  }
197
234
 
198
235
  getContextValueFromFormValue(
@@ -7,10 +7,11 @@ import {
7
7
  isGeospatialState
8
8
  } from './FormComponent.js'
9
9
  import { getGeospatialSchema } from './helpers/geospatial.js'
10
+ import { type RenderContext } from './types.js'
11
+ import { type Translator } from '../i18n/types.js'
10
12
  import { messageTemplate } from '../pageControllers/validationOptions.js'
11
13
  import {
12
14
  type ErrorMessageTemplateList,
13
- type FormPayload,
14
15
  type FormState,
15
16
  type FormStateValue,
16
17
  type FormSubmissionError,
@@ -31,13 +32,11 @@ export class GeospatialField extends FormComponent {
31
32
 
32
33
  const { options } = def
33
34
 
34
- const formSchema = getGeospatialSchema(def)
35
- .label(this.label)
36
- .messages({
37
- 'array.min': messageTemplate.featuresMin as string,
38
- 'array.max': messageTemplate.featuresMax as string,
39
- 'array.length': messageTemplate.featuresLength as string
40
- })
35
+ const formSchema = getGeospatialSchema(def).label(this.label).messages({
36
+ 'array.min': messageTemplate.featuresMin,
37
+ 'array.max': messageTemplate.featuresMax,
38
+ 'array.length': messageTemplate.featuresLength
39
+ })
41
40
 
42
41
  this.formSchema = formSchema
43
42
  this.stateSchema = formSchema.default(null)
@@ -58,20 +57,26 @@ export class GeospatialField extends FormComponent {
58
57
  return this.isValue(value) ? value : undefined
59
58
  }
60
59
 
61
- getDisplayStringFromFormValue(features: GeospatialState | undefined): string {
60
+ getDisplayStringFromFormValue(
61
+ features: GeospatialState | undefined,
62
+ translator: Translator
63
+ ): string {
62
64
  if (!features?.length) {
63
65
  return ''
64
66
  }
65
67
 
66
- const unit = features.length === 1 ? 'location' : 'locations'
67
-
68
- return `Added ${features.length} ${unit}`
68
+ return translator.t('components.geospatialField.added', {
69
+ count: features.length
70
+ })
69
71
  }
70
72
 
71
- getDisplayStringFromState(state: FormSubmissionState) {
73
+ getDisplayStringFromState(
74
+ state: FormSubmissionState,
75
+ translator: Translator
76
+ ) {
72
77
  const features = this.getFormValueFromState(state)
73
78
 
74
- return this.getDisplayStringFromFormValue(features)
79
+ return this.getDisplayStringFromFormValue(features, translator)
75
80
  }
76
81
 
77
82
  getContextValueFromFormValue(
@@ -86,8 +91,8 @@ export class GeospatialField extends FormComponent {
86
91
  return this.getContextValueFromFormValue(features)
87
92
  }
88
93
 
89
- getViewModel(payload: FormPayload, errors?: FormSubmissionError[]) {
90
- const viewModel = super.getViewModel(payload, errors)
94
+ getViewModel(context: RenderContext) {
95
+ const viewModel = super.getViewModel(context)
91
96
  const value =
92
97
  typeof viewModel.value === 'string'
93
98
  ? viewModel.value
@@ -101,16 +106,25 @@ export class GeospatialField extends FormComponent {
101
106
  }
102
107
  }
103
108
 
104
- getErrors(errors?: FormSubmissionError[]): FormSubmissionError[] | undefined {
105
- const fieldErrors = super.getErrors(errors)
109
+ getErrors(
110
+ translator: Translator,
111
+ errors?: FormSubmissionError[]
112
+ ): FormSubmissionError[] | undefined {
113
+ const fieldErrors = super.getErrors(translator, errors)
106
114
 
107
115
  fieldErrors?.forEach((err) => {
108
116
  if (err.name === 'description') {
109
117
  err.href = `#description_${err.path[1]}`
110
- err.text = `Enter description for location ${Number(err.path[1]) + 1}`
118
+ err.text = translator.t(
119
+ 'components.geospatialField.validation.descriptionRequired',
120
+ { count: Number(err.path[1]) + 1 }
121
+ )
111
122
  } else if (typeof err.name === 'number' && err.context?.country) {
112
123
  err.href = `#description_${err.path[1]}`
113
- err.text = `Location ${Number(err.path[1]) + 1} must be in ${err.context.country}`
124
+ err.text = translator.t(
125
+ 'components.geospatialField.validation.wrongCountry',
126
+ { count: Number(err.path[1]) + 1, country: err.context.country }
127
+ )
114
128
  }
115
129
  })
116
130
 
@@ -118,9 +132,10 @@ export class GeospatialField extends FormComponent {
118
132
  }
119
133
 
120
134
  getViewErrors(
135
+ translator: Translator,
121
136
  errors?: FormSubmissionError[]
122
137
  ): FormSubmissionError[] | undefined {
123
- return this.getErrors(errors)
138
+ return this.getErrors(translator, errors)
124
139
  }
125
140
 
126
141
  isValue(value?: FormStateValue | FormState): value is GeospatialState {