@defra/forms-engine-plugin 4.23.0 → 5.0.0-alpha.1

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 (347) hide show
  1. package/.public/assets-manifest.json +3 -5
  2. package/.public/javascripts/im-core.min.js +2 -0
  3. package/.public/javascripts/im-core.min.js.map +1 -0
  4. package/.public/javascripts/shared.min.js +1 -1
  5. package/.public/javascripts/shared.min.js.map +1 -1
  6. package/.public/javascripts/vendor/@defra.min.js +1 -1
  7. package/.public/javascripts/vendor/@defra.min.js.map +1 -1
  8. package/.public/stylesheets/application.min.css +1 -1
  9. package/.public/stylesheets/application.min.css.map +1 -1
  10. package/.server/client/javascripts/geospatial-map.js +8 -6
  11. package/.server/client/javascripts/geospatial-map.js.map +1 -1
  12. package/.server/client/javascripts/location-map.js +8 -1
  13. package/.server/client/javascripts/location-map.js.map +1 -1
  14. package/.server/client/javascripts/map.d.ts +6 -0
  15. package/.server/client/javascripts/map.js +10 -0
  16. package/.server/client/javascripts/map.js.map +1 -1
  17. package/.server/client/javascripts/sssi-dataset.d.ts +34 -0
  18. package/.server/client/javascripts/sssi-dataset.js +101 -0
  19. package/.server/client/javascripts/sssi-dataset.js.map +1 -0
  20. package/.server/client/stylesheets/shared.scss +0 -2
  21. package/.server/server/forms/register-as-a-unicorn-breeder.yaml +0 -14
  22. package/.server/server/forms/simple-form.yaml +106 -3
  23. package/.server/server/plugins/engine/components/AutocompleteField.d.ts +11 -11
  24. package/.server/server/plugins/engine/components/AutocompleteField.js +2 -2
  25. package/.server/server/plugins/engine/components/AutocompleteField.js.map +1 -1
  26. package/.server/server/plugins/engine/components/CheckboxesField.d.ts +3 -2
  27. package/.server/server/plugins/engine/components/CheckboxesField.js +4 -9
  28. package/.server/server/plugins/engine/components/CheckboxesField.js.map +1 -1
  29. package/.server/server/plugins/engine/components/ComponentCollection.d.ts +8 -7
  30. package/.server/server/plugins/engine/components/ComponentCollection.js +106 -51
  31. package/.server/server/plugins/engine/components/ComponentCollection.js.map +1 -1
  32. package/.server/server/plugins/engine/components/DatePartsField.d.ts +8 -6
  33. package/.server/server/plugins/engine/components/DatePartsField.js +27 -9
  34. package/.server/server/plugins/engine/components/DatePartsField.js.map +1 -1
  35. package/.server/server/plugins/engine/components/DeclarationField.d.ts +13 -11
  36. package/.server/server/plugins/engine/components/DeclarationField.js +31 -9
  37. package/.server/server/plugins/engine/components/DeclarationField.js.map +1 -1
  38. package/.server/server/plugins/engine/components/EastingNorthingField.d.ts +8 -5
  39. package/.server/server/plugins/engine/components/EastingNorthingField.js +42 -22
  40. package/.server/server/plugins/engine/components/EastingNorthingField.js.map +1 -1
  41. package/.server/server/plugins/engine/components/EmailAddressField.d.ts +11 -14
  42. package/.server/server/plugins/engine/components/EmailAddressField.js +2 -2
  43. package/.server/server/plugins/engine/components/EmailAddressField.js.map +1 -1
  44. package/.server/server/plugins/engine/components/FileUploadField.d.ts +14 -12
  45. package/.server/server/plugins/engine/components/FileUploadField.js +22 -12
  46. package/.server/server/plugins/engine/components/FileUploadField.js.map +1 -1
  47. package/.server/server/plugins/engine/components/FormComponent.d.ts +21 -12
  48. package/.server/server/plugins/engine/components/FormComponent.js +33 -14
  49. package/.server/server/plugins/engine/components/FormComponent.js.map +1 -1
  50. package/.server/server/plugins/engine/components/GeospatialField.d.ts +15 -12
  51. package/.server/server/plugins/engine/components/GeospatialField.js +21 -13
  52. package/.server/server/plugins/engine/components/GeospatialField.js.map +1 -1
  53. package/.server/server/plugins/engine/components/LatLongField.d.ts +8 -5
  54. package/.server/server/plugins/engine/components/LatLongField.js +32 -20
  55. package/.server/server/plugins/engine/components/LatLongField.js.map +1 -1
  56. package/.server/server/plugins/engine/components/ListFormComponent.d.ts +7 -6
  57. package/.server/server/plugins/engine/components/ListFormComponent.js +19 -7
  58. package/.server/server/plugins/engine/components/ListFormComponent.js.map +1 -1
  59. package/.server/server/plugins/engine/components/LocationFieldBase.d.ts +17 -16
  60. package/.server/server/plugins/engine/components/LocationFieldBase.js +2 -2
  61. package/.server/server/plugins/engine/components/LocationFieldBase.js.map +1 -1
  62. package/.server/server/plugins/engine/components/LocationFieldHelpers.d.ts +8 -3
  63. package/.server/server/plugins/engine/components/LocationFieldHelpers.js +14 -3
  64. package/.server/server/plugins/engine/components/LocationFieldHelpers.js.map +1 -1
  65. package/.server/server/plugins/engine/components/Markdown.d.ts +8 -7
  66. package/.server/server/plugins/engine/components/Markdown.js +5 -2
  67. package/.server/server/plugins/engine/components/Markdown.js.map +1 -1
  68. package/.server/server/plugins/engine/components/MonthYearField.d.ts +9 -7
  69. package/.server/server/plugins/engine/components/MonthYearField.js +26 -8
  70. package/.server/server/plugins/engine/components/MonthYearField.js.map +1 -1
  71. package/.server/server/plugins/engine/components/MultilineTextField.d.ts +10 -9
  72. package/.server/server/plugins/engine/components/MultilineTextField.js +2 -2
  73. package/.server/server/plugins/engine/components/MultilineTextField.js.map +1 -1
  74. package/.server/server/plugins/engine/components/NationalGridFieldNumberField.d.ts +2 -1
  75. package/.server/server/plugins/engine/components/NationalGridFieldNumberField.js +14 -6
  76. package/.server/server/plugins/engine/components/NationalGridFieldNumberField.js.map +1 -1
  77. package/.server/server/plugins/engine/components/NumberField.d.ts +10 -9
  78. package/.server/server/plugins/engine/components/NumberField.js +2 -2
  79. package/.server/server/plugins/engine/components/NumberField.js.map +1 -1
  80. package/.server/server/plugins/engine/components/OsGridRefField.d.ts +2 -1
  81. package/.server/server/plugins/engine/components/OsGridRefField.js +14 -6
  82. package/.server/server/plugins/engine/components/OsGridRefField.js.map +1 -1
  83. package/.server/server/plugins/engine/components/PaymentField.d.ts +12 -10
  84. package/.server/server/plugins/engine/components/PaymentField.js +21 -8
  85. package/.server/server/plugins/engine/components/PaymentField.js.map +1 -1
  86. package/.server/server/plugins/engine/components/SelectField.d.ts +11 -11
  87. package/.server/server/plugins/engine/components/SelectField.js +2 -2
  88. package/.server/server/plugins/engine/components/SelectField.js.map +1 -1
  89. package/.server/server/plugins/engine/components/SelectionControlField.d.ts +4 -4
  90. package/.server/server/plugins/engine/components/SelectionControlField.js +2 -2
  91. package/.server/server/plugins/engine/components/SelectionControlField.js.map +1 -1
  92. package/.server/server/plugins/engine/components/TelephoneNumberField.d.ts +10 -9
  93. package/.server/server/plugins/engine/components/TelephoneNumberField.js +2 -2
  94. package/.server/server/plugins/engine/components/TelephoneNumberField.js.map +1 -1
  95. package/.server/server/plugins/engine/components/UkAddressField.d.ts +12 -10
  96. package/.server/server/plugins/engine/components/UkAddressField.js +29 -17
  97. package/.server/server/plugins/engine/components/UkAddressField.js.map +1 -1
  98. package/.server/server/plugins/engine/components/YesNoField.d.ts +3 -0
  99. package/.server/server/plugins/engine/components/YesNoField.js +9 -0
  100. package/.server/server/plugins/engine/components/YesNoField.js.map +1 -1
  101. package/.server/server/plugins/engine/components/helpers/components.d.ts +3 -2
  102. package/.server/server/plugins/engine/components/helpers/components.js +11 -8
  103. package/.server/server/plugins/engine/components/helpers/components.js.map +1 -1
  104. package/.server/server/plugins/engine/components/types.d.ts +8 -1
  105. package/.server/server/plugins/engine/components/types.js.map +1 -1
  106. package/.server/server/plugins/engine/configureEnginePlugin.js +8 -1
  107. package/.server/server/plugins/engine/configureEnginePlugin.js.map +1 -1
  108. package/.server/server/plugins/engine/form-context.d.ts +1 -0
  109. package/.server/server/plugins/engine/form-context.js +4 -2
  110. package/.server/server/plugins/engine/form-context.js.map +1 -1
  111. package/.server/server/plugins/engine/helpers.d.ts +1 -1
  112. package/.server/server/plugins/engine/helpers.js +8 -13
  113. package/.server/server/plugins/engine/helpers.js.map +1 -1
  114. package/.server/server/plugins/engine/i18n/buildValidationMessages.d.ts +39 -0
  115. package/.server/server/plugins/engine/i18n/buildValidationMessages.js +50 -0
  116. package/.server/server/plugins/engine/i18n/buildValidationMessages.js.map +1 -0
  117. package/.server/server/plugins/engine/i18n/createFormTranslator.d.ts +5 -0
  118. package/.server/server/plugins/engine/i18n/createFormTranslator.js +18 -0
  119. package/.server/server/plugins/engine/i18n/createFormTranslator.js.map +1 -0
  120. package/.server/server/plugins/engine/i18n/createTranslator.d.ts +9 -0
  121. package/.server/server/plugins/engine/i18n/createTranslator.js +51 -0
  122. package/.server/server/plugins/engine/i18n/createTranslator.js.map +1 -0
  123. package/.server/server/plugins/engine/i18n/extractBaseTranslations.d.ts +5 -0
  124. package/.server/server/plugins/engine/i18n/extractBaseTranslations.js +57 -0
  125. package/.server/server/plugins/engine/i18n/extractBaseTranslations.js.map +1 -0
  126. package/.server/server/plugins/engine/i18n/index.d.ts +18 -0
  127. package/.server/server/plugins/engine/i18n/index.js +71 -0
  128. package/.server/server/plugins/engine/i18n/index.js.map +1 -0
  129. package/.server/server/plugins/engine/i18n/translations/cy.json +271 -0
  130. package/.server/server/plugins/engine/i18n/translations/en-GB.json +271 -0
  131. package/.server/server/plugins/engine/i18n/types.d.ts +41 -0
  132. package/.server/server/plugins/engine/i18n/types.js +2 -0
  133. package/.server/server/plugins/engine/i18n/types.js.map +1 -0
  134. package/.server/server/plugins/engine/index.js +3 -2
  135. package/.server/server/plugins/engine/index.js.map +1 -1
  136. package/.server/server/plugins/engine/models/FormModel.d.ts +9 -1
  137. package/.server/server/plugins/engine/models/FormModel.js +44 -18
  138. package/.server/server/plugins/engine/models/FormModel.js.map +1 -1
  139. package/.server/server/plugins/engine/models/SummaryViewModel.d.ts +5 -2
  140. package/.server/server/plugins/engine/models/SummaryViewModel.js +44 -18
  141. package/.server/server/plugins/engine/models/SummaryViewModel.js.map +1 -1
  142. package/.server/server/plugins/engine/options.js +2 -1
  143. package/.server/server/plugins/engine/options.js.map +1 -1
  144. package/.server/server/plugins/engine/outputFormatters/adapter/v1.js +4 -0
  145. package/.server/server/plugins/engine/outputFormatters/adapter/v1.js.map +1 -1
  146. package/.server/server/plugins/engine/outputFormatters/human/v1.js +2 -1
  147. package/.server/server/plugins/engine/outputFormatters/human/v1.js.map +1 -1
  148. package/.server/server/plugins/engine/outputFormatters/machine/v1.js +7 -6
  149. package/.server/server/plugins/engine/outputFormatters/machine/v1.js.map +1 -1
  150. package/.server/server/plugins/engine/pageControllers/FileUploadPageController.d.ts +2 -1
  151. package/.server/server/plugins/engine/pageControllers/FileUploadPageController.js +6 -3
  152. package/.server/server/plugins/engine/pageControllers/FileUploadPageController.js.map +1 -1
  153. package/.server/server/plugins/engine/pageControllers/PageController.d.ts +3 -1
  154. package/.server/server/plugins/engine/pageControllers/PageController.js +11 -1
  155. package/.server/server/plugins/engine/pageControllers/PageController.js.map +1 -1
  156. package/.server/server/plugins/engine/pageControllers/QuestionPageController.d.ts +4 -2
  157. package/.server/server/plugins/engine/pageControllers/QuestionPageController.js +52 -21
  158. package/.server/server/plugins/engine/pageControllers/QuestionPageController.js.map +1 -1
  159. package/.server/server/plugins/engine/pageControllers/RepeatPageController.d.ts +3 -2
  160. package/.server/server/plugins/engine/pageControllers/RepeatPageController.js +63 -26
  161. package/.server/server/plugins/engine/pageControllers/RepeatPageController.js.map +1 -1
  162. package/.server/server/plugins/engine/pageControllers/StartPageController.d.ts +3 -1
  163. package/.server/server/plugins/engine/pageControllers/StartPageController.js +2 -2
  164. package/.server/server/plugins/engine/pageControllers/StartPageController.js.map +1 -1
  165. package/.server/server/plugins/engine/pageControllers/StatusPageController.js +12 -2
  166. package/.server/server/plugins/engine/pageControllers/StatusPageController.js.map +1 -1
  167. package/.server/server/plugins/engine/pageControllers/SummaryPageController.d.ts +4 -3
  168. package/.server/server/plugins/engine/pageControllers/SummaryPageController.js +44 -28
  169. package/.server/server/plugins/engine/pageControllers/SummaryPageController.js.map +1 -1
  170. package/.server/server/plugins/engine/pageControllers/__stubs__/translator.d.ts +2 -0
  171. package/.server/server/plugins/engine/pageControllers/__stubs__/translator.js +24 -0
  172. package/.server/server/plugins/engine/pageControllers/__stubs__/translator.js.map +1 -0
  173. package/.server/server/plugins/engine/pageControllers/errors.d.ts +1 -1
  174. package/.server/server/plugins/engine/pageControllers/errors.js +3 -2
  175. package/.server/server/plugins/engine/pageControllers/errors.js.map +1 -1
  176. package/.server/server/plugins/engine/pageControllers/helpers/submission.d.ts +3 -2
  177. package/.server/server/plugins/engine/pageControllers/helpers/submission.js +4 -4
  178. package/.server/server/plugins/engine/pageControllers/helpers/submission.js.map +1 -1
  179. package/.server/server/plugins/engine/pageControllers/validationOptions.d.ts +7 -3
  180. package/.server/server/plugins/engine/pageControllers/validationOptions.js +34 -33
  181. package/.server/server/plugins/engine/pageControllers/validationOptions.js.map +1 -1
  182. package/.server/server/plugins/engine/plugin.js +2 -0
  183. package/.server/server/plugins/engine/plugin.js.map +1 -1
  184. package/.server/server/plugins/engine/routes/index.js +4 -1
  185. package/.server/server/plugins/engine/routes/index.js.map +1 -1
  186. package/.server/server/plugins/engine/routes/questions.js +5 -2
  187. package/.server/server/plugins/engine/routes/questions.js.map +1 -1
  188. package/.server/server/plugins/engine/types/index.d.ts +1 -0
  189. package/.server/server/plugins/engine/types/index.js.map +1 -1
  190. package/.server/server/plugins/engine/types/schema.js +1 -0
  191. package/.server/server/plugins/engine/types/schema.js.map +1 -1
  192. package/.server/server/plugins/engine/types.d.ts +12 -1
  193. package/.server/server/plugins/engine/types.js.map +1 -1
  194. package/.server/server/plugins/engine/views/components/_location-field-base.html +4 -2
  195. package/.server/server/plugins/engine/views/components/fileuploadfield.html +3 -3
  196. package/.server/server/plugins/engine/views/components/geospatialfield.html +4 -1
  197. package/.server/server/plugins/engine/views/components/nationalgridfieldnumberfield.html +1 -1
  198. package/.server/server/plugins/engine/views/components/osgridreffield.html +1 -1
  199. package/.server/server/plugins/engine/views/components/paymentfield.html +8 -8
  200. package/.server/server/plugins/engine/views/components/ukaddressfield.html +4 -4
  201. package/.server/server/plugins/engine/views/confirmation.html +4 -4
  202. package/.server/server/plugins/engine/views/exit.html +4 -4
  203. package/.server/server/plugins/engine/views/file-upload.html +3 -3
  204. package/.server/server/plugins/engine/views/index.html +3 -3
  205. package/.server/server/plugins/engine/views/item-delete.html +1 -1
  206. package/.server/server/plugins/engine/views/partials/form.html +3 -3
  207. package/.server/server/plugins/engine/views/partials/preview-banner.html +4 -4
  208. package/.server/server/plugins/engine/views/partials/warn-missing-notification-email.html +4 -5
  209. package/.server/server/plugins/engine/views/repeat-list-summary.html +4 -4
  210. package/.server/server/plugins/engine/views/summary.html +14 -7
  211. package/.server/server/plugins/map/routes/index.js +1 -1
  212. package/.server/server/plugins/map/routes/index.js.map +1 -1
  213. package/.server/server/plugins/map/types.d.ts +1 -25
  214. package/.server/server/plugins/map/types.js +1 -16
  215. package/.server/server/plugins/map/types.js.map +1 -1
  216. package/.server/server/plugins/nunjucks/enviroment.test.js +10 -0
  217. package/.server/server/plugins/nunjucks/enviroment.test.js.map +1 -1
  218. package/.server/server/plugins/nunjucks/environment.d.ts +8 -0
  219. package/.server/server/plugins/nunjucks/environment.js +13 -0
  220. package/.server/server/plugins/nunjucks/environment.js.map +1 -1
  221. package/.server/server/plugins/nunjucks/filters/answer.js +9 -1
  222. package/.server/server/plugins/nunjucks/filters/answer.js.map +1 -1
  223. package/.server/server/plugins/nunjucks/filters/answer.test.js +13 -2
  224. package/.server/server/plugins/nunjucks/filters/answer.test.js.map +1 -1
  225. package/.server/server/plugins/nunjucks/filters/field.d.ts +1 -1
  226. package/.server/server/plugins/postcode-lookup/models/index.d.ts +24 -19
  227. package/.server/server/plugins/postcode-lookup/models/index.js +83 -76
  228. package/.server/server/plugins/postcode-lookup/models/index.js.map +1 -1
  229. package/.server/server/plugins/postcode-lookup/routes/index.js +7 -13
  230. package/.server/server/plugins/postcode-lookup/routes/index.js.map +1 -1
  231. package/.server/server/plugins/postcode-lookup/types.d.ts +1 -0
  232. package/.server/server/plugins/postcode-lookup/types.js +1 -0
  233. package/.server/server/plugins/postcode-lookup/types.js.map +1 -1
  234. package/.server/server/plugins/postcode-lookup/views/postcode-lookup-details.html +3 -3
  235. package/.server/server/types.d.ts +2 -1
  236. package/.server/server/types.js.map +1 -1
  237. package/.server/server/utils/utils.d.ts +5 -0
  238. package/.server/server/utils/utils.js +16 -0
  239. package/.server/server/utils/utils.js.map +1 -1
  240. package/.server/typings/hapi/index.d.js.map +1 -1
  241. package/package.json +5 -4
  242. package/src/client/javascripts/geospatial-map.js +10 -6
  243. package/src/client/javascripts/location-map.js +11 -0
  244. package/src/client/javascripts/map.js +10 -0
  245. package/src/client/javascripts/sssi-dataset.js +106 -0
  246. package/src/client/stylesheets/shared.scss +0 -2
  247. package/src/server/forms/register-as-a-unicorn-breeder.yaml +0 -14
  248. package/src/server/forms/simple-form.yaml +106 -3
  249. package/src/server/plugins/engine/components/AutocompleteField.ts +3 -6
  250. package/src/server/plugins/engine/components/CheckboxesField.ts +12 -11
  251. package/src/server/plugins/engine/components/ComponentCollection.ts +143 -61
  252. package/src/server/plugins/engine/components/DatePartsField.ts +33 -11
  253. package/src/server/plugins/engine/components/DeclarationField.ts +37 -14
  254. package/src/server/plugins/engine/components/EastingNorthingField.ts +83 -22
  255. package/src/server/plugins/engine/components/EmailAddressField.ts +4 -7
  256. package/src/server/plugins/engine/components/FileUploadField.ts +28 -22
  257. package/src/server/plugins/engine/components/FormComponent.ts +49 -12
  258. package/src/server/plugins/engine/components/GeospatialField.ts +38 -21
  259. package/src/server/plugins/engine/components/LatLongField.ts +52 -21
  260. package/src/server/plugins/engine/components/ListFormComponent.ts +26 -10
  261. package/src/server/plugins/engine/components/LocationFieldBase.ts +5 -8
  262. package/src/server/plugins/engine/components/LocationFieldHelpers.ts +24 -4
  263. package/src/server/plugins/engine/components/Markdown.ts +7 -3
  264. package/src/server/plugins/engine/components/MonthYearField.ts +32 -10
  265. package/src/server/plugins/engine/components/MultilineTextField.ts +5 -8
  266. package/src/server/plugins/engine/components/NationalGridFieldNumberField.ts +25 -11
  267. package/src/server/plugins/engine/components/NumberField.ts +3 -4
  268. package/src/server/plugins/engine/components/OsGridRefField.ts +25 -9
  269. package/src/server/plugins/engine/components/PaymentField.ts +22 -12
  270. package/src/server/plugins/engine/components/SelectField.ts +3 -6
  271. package/src/server/plugins/engine/components/SelectionControlField.ts +7 -8
  272. package/src/server/plugins/engine/components/TelephoneNumberField.ts +4 -7
  273. package/src/server/plugins/engine/components/UkAddressField.ts +33 -18
  274. package/src/server/plugins/engine/components/YesNoField.ts +10 -0
  275. package/src/server/plugins/engine/components/helpers/components.ts +13 -6
  276. package/src/server/plugins/engine/components/types.ts +9 -0
  277. package/src/server/plugins/engine/configureEnginePlugin.ts +12 -1
  278. package/src/server/plugins/engine/form-context.ts +8 -2
  279. package/src/server/plugins/engine/helpers.ts +10 -18
  280. package/src/server/plugins/engine/i18n/buildValidationMessages.ts +69 -0
  281. package/src/server/plugins/engine/i18n/createFormTranslator.ts +33 -0
  282. package/src/server/plugins/engine/i18n/createTranslator.ts +61 -0
  283. package/src/server/plugins/engine/i18n/extractBaseTranslations.ts +61 -0
  284. package/src/server/plugins/engine/i18n/index.ts +80 -0
  285. package/src/server/plugins/engine/i18n/translations/cy.json +271 -0
  286. package/src/server/plugins/engine/i18n/translations/en-GB.json +271 -0
  287. package/src/server/plugins/engine/i18n/types.ts +62 -0
  288. package/src/server/plugins/engine/index.ts +4 -2
  289. package/src/server/plugins/engine/models/FormModel.ts +59 -23
  290. package/src/server/plugins/engine/models/SummaryViewModel.ts +68 -25
  291. package/src/server/plugins/engine/options.js +2 -1
  292. package/src/server/plugins/engine/outputFormatters/adapter/v1.ts +5 -0
  293. package/src/server/plugins/engine/outputFormatters/human/v1.ts +2 -3
  294. package/src/server/plugins/engine/outputFormatters/machine/v1.ts +9 -8
  295. package/src/server/plugins/engine/pageControllers/FileUploadPageController.ts +7 -3
  296. package/src/server/plugins/engine/pageControllers/PageController.ts +12 -1
  297. package/src/server/plugins/engine/pageControllers/QuestionPageController.ts +53 -21
  298. package/src/server/plugins/engine/pageControllers/RepeatPageController.ts +66 -29
  299. package/src/server/plugins/engine/pageControllers/StartPageController.ts +7 -2
  300. package/src/server/plugins/engine/pageControllers/StatusPageController.ts +10 -2
  301. package/src/server/plugins/engine/pageControllers/SummaryPageController.ts +48 -22
  302. package/src/server/plugins/engine/pageControllers/__stubs__/translator.ts +28 -0
  303. package/src/server/plugins/engine/pageControllers/errors.ts +4 -2
  304. package/src/server/plugins/engine/pageControllers/helpers/submission.ts +11 -4
  305. package/src/server/plugins/engine/pageControllers/validationOptions.ts +43 -53
  306. package/src/server/plugins/engine/plugin.ts +2 -0
  307. package/src/server/plugins/engine/routes/index.ts +9 -1
  308. package/src/server/plugins/engine/routes/questions.ts +5 -1
  309. package/src/server/plugins/engine/types/index.ts +5 -0
  310. package/src/server/plugins/engine/types/schema.ts +1 -0
  311. package/src/server/plugins/engine/types.ts +10 -0
  312. package/src/server/plugins/engine/views/components/_location-field-base.html +4 -2
  313. package/src/server/plugins/engine/views/components/fileuploadfield.html +3 -3
  314. package/src/server/plugins/engine/views/components/geospatialfield.html +4 -1
  315. package/src/server/plugins/engine/views/components/nationalgridfieldnumberfield.html +1 -1
  316. package/src/server/plugins/engine/views/components/osgridreffield.html +1 -1
  317. package/src/server/plugins/engine/views/components/paymentfield.html +8 -8
  318. package/src/server/plugins/engine/views/components/ukaddressfield.html +4 -4
  319. package/src/server/plugins/engine/views/confirmation.html +4 -4
  320. package/src/server/plugins/engine/views/exit.html +4 -4
  321. package/src/server/plugins/engine/views/file-upload.html +3 -3
  322. package/src/server/plugins/engine/views/index.html +3 -3
  323. package/src/server/plugins/engine/views/item-delete.html +1 -1
  324. package/src/server/plugins/engine/views/partials/form.html +3 -3
  325. package/src/server/plugins/engine/views/partials/preview-banner.html +4 -4
  326. package/src/server/plugins/engine/views/partials/warn-missing-notification-email.html +4 -5
  327. package/src/server/plugins/engine/views/repeat-list-summary.html +4 -4
  328. package/src/server/plugins/engine/views/summary.html +14 -7
  329. package/src/server/plugins/map/routes/index.js +1 -1
  330. package/src/server/plugins/map/types.js +1 -16
  331. package/src/server/plugins/nunjucks/environment.js +14 -0
  332. package/src/server/plugins/nunjucks/filters/answer.js +12 -1
  333. package/src/server/plugins/postcode-lookup/models/index.js +144 -87
  334. package/src/server/plugins/postcode-lookup/routes/index.js +13 -16
  335. package/src/server/plugins/postcode-lookup/types.js +1 -0
  336. package/src/server/plugins/postcode-lookup/views/postcode-lookup-details.html +3 -3
  337. package/src/server/types.ts +2 -0
  338. package/src/server/utils/utils.js +14 -0
  339. package/src/typings/hapi/index.d.ts +1 -0
  340. package/.public/javascripts/im-search-plugin.min.js +0 -2
  341. package/.public/javascripts/im-search-plugin.min.js.map +0 -1
  342. package/.public/javascripts/vendor/preact.min.js +0 -2
  343. package/.public/javascripts/vendor/preact.min.js.map +0 -1
  344. package/.server/server/plugins/engine/components/constants.d.ts +0 -1
  345. package/.server/server/plugins/engine/components/constants.js +0 -2
  346. package/.server/server/plugins/engine/components/constants.js.map +0 -1
  347. package/src/server/plugins/engine/components/constants.ts +0 -1
@@ -21,7 +21,6 @@ import {
21
21
  } from '../../../constants.js'
22
22
  import { ComponentCollection } from '../components/ComponentCollection.js'
23
23
  import { PaymentField } from '../components/PaymentField.js'
24
- import { optionalText } from '../components/constants.js'
25
24
  import { type BackLink } from '../components/types.js'
26
25
  import {
27
26
  checkFormStatus,
@@ -31,6 +30,7 @@ import {
31
30
  normalisePath,
32
31
  proceed
33
32
  } from '../helpers.js'
33
+ import { type Translator } from '../i18n/types.js'
34
34
  import { type FormModel } from '../models/index.js'
35
35
  import { PageController } from './PageController.js'
36
36
  import { prefillStateFromQueryParameters } from './helpers/state.js'
@@ -118,18 +118,28 @@ export class QuestionPageController extends PageController {
118
118
  * Used for mapping form payloads and errors to govuk-frontend's template api, so a page can be rendered
119
119
  * @param request - the hapi request
120
120
  * @param context - the form context
121
+ * @param translator - optional per-request translator pair
121
122
  */
122
123
  getViewModel(
123
124
  request: FormContextRequest,
124
- context: FormContext
125
+ context: FormContext,
126
+ translator: Translator
125
127
  ): FormPageViewModel {
126
128
  const { collection, viewModel } = this
127
- const { query } = request
128
129
  const { payload, errors } = context
129
130
 
130
- let { pageTitle, showTitle } = viewModel
131
+ const { t, tPage, tSection } = translator
132
+
133
+ let { showTitle, sectionTitle } = viewModel
131
134
 
132
- const components = collection.getViewModel(payload, errors, query)
135
+ let pageTitle = this.pageDef.title ? tPage(this.pageDef, 'title') : ''
136
+
137
+ if (this.section) {
138
+ sectionTitle =
139
+ this.section.hideTitle !== true ? tSection(this.section, 'title') : ''
140
+ }
141
+
142
+ const components = collection.getViewModel({ payload, errors, translator })
133
143
  const formComponents = components.filter(
134
144
  ({ isFormComponent }) => isFormComponent
135
145
  )
@@ -161,13 +171,17 @@ export class QuestionPageController extends PageController {
161
171
  const isOptional =
162
172
  this.collection.fields.at(0)?.options.required === false
163
173
 
164
- if (pageTitle) {
165
- labelOrLegend.text = isOptional
166
- ? `${pageTitle}${optionalText}`
167
- : pageTitle
174
+ if (!pageTitle) {
175
+ pageTitle = labelOrLegend.text
168
176
  }
177
+ labelOrLegend.text = isOptional
178
+ ? `${pageTitle} ${t('common.optional')}`
179
+ : pageTitle
180
+ }
169
181
 
170
- pageTitle = pageTitle || labelOrLegend.text
182
+ // Fallback if still no pageTitle set
183
+ if (!pageTitle) {
184
+ pageTitle = labelOrLegend.text
171
185
  }
172
186
  }
173
187
 
@@ -216,8 +230,10 @@ export class QuestionPageController extends PageController {
216
230
 
217
231
  return {
218
232
  ...viewModel,
219
- backLink: this.getBackLink(request, context),
233
+ backLink: this.getBackLink(request, context, t),
220
234
  context,
235
+ pageTitle,
236
+ sectionTitle,
221
237
  showTitle,
222
238
  components,
223
239
  errors,
@@ -450,14 +466,17 @@ export class QuestionPageController extends PageController {
450
466
  const { collection, model, viewName } = this
451
467
  const { evaluationState } = context
452
468
 
469
+ const translator = this.getTranslator(request)
470
+ const { t } = translator
471
+
453
472
  // Copy any URL params into the form state (if not already done so)
454
473
  if (await prefillStateFromQueryParameters(request, this)) {
455
474
  // Forward to same page without query string
456
475
  return h.redirect(request.url.pathname)
457
476
  }
458
477
 
459
- const viewModel = this.getViewModel(request, context)
460
- viewModel.errors = collection.getViewErrors(viewModel.errors)
478
+ const viewModel = this.getViewModel(request, context, translator)
479
+ viewModel.errors = collection.getViewErrors(translator, viewModel.errors)
461
480
 
462
481
  const flashedError = request.yar.flash(COMPONENT_STATE_ERROR)
463
482
  const flashedErrors = !Array.isArray(flashedError) ? [flashedError] : []
@@ -484,7 +503,10 @@ export class QuestionPageController extends PageController {
484
503
  viewModel.hasMissingNotificationEmail =
485
504
  await this.hasMissingNotificationEmail(request, context)
486
505
 
487
- return h.view(viewName, viewModel)
506
+ return h.view(viewName, {
507
+ ...viewModel,
508
+ t
509
+ })
488
510
  }
489
511
  }
490
512
 
@@ -515,7 +537,8 @@ export class QuestionPageController extends PageController {
515
537
  */
516
538
  protected getBackLink(
517
539
  request: FormContextRequest,
518
- context: FormContext
540
+ context: FormContext,
541
+ t: (key: string, opts?: Record<string, unknown>) => string
519
542
  ): BackLink | undefined {
520
543
  const { pageDef } = this
521
544
  const { path, query } = request
@@ -529,8 +552,8 @@ export class QuestionPageController extends PageController {
529
552
  return {
530
553
  text:
531
554
  hasRepeater(pageDef) && itemId
532
- ? 'Go back to add another'
533
- : 'Go back to check answers',
555
+ ? t('pages.question.backToAddAnother')
556
+ : t('pages.question.backToCheckAnswers'),
534
557
  href: returnUrl
535
558
  }
536
559
  }
@@ -548,7 +571,7 @@ export class QuestionPageController extends PageController {
548
571
 
549
572
  // Default back link
550
573
  return {
551
- text: 'Back',
574
+ text: t('common.back'),
552
575
  href: this.getHref(backPath)
553
576
  }
554
577
  }
@@ -563,6 +586,9 @@ export class QuestionPageController extends PageController {
563
586
  const { isForceAccess, state, evaluationState } = context
564
587
  const action = request.payload.action
565
588
 
589
+ const translator = this.getTranslator(request)
590
+ const { t } = translator
591
+
566
592
  if (action?.startsWith(FormAction.External)) {
567
593
  return await this.dispatchExternal(request, h, context)
568
594
  }
@@ -572,8 +598,11 @@ export class QuestionPageController extends PageController {
572
598
  * @todo Refactor to match POST REDIRECT GET pattern
573
599
  */
574
600
  if (context.errors || isForceAccess) {
575
- const viewModel = this.getViewModel(request, context)
576
- viewModel.errors = collection.getViewErrors(viewModel.errors)
601
+ const viewModel = this.getViewModel(request, context, translator)
602
+ viewModel.errors = collection.getViewErrors(
603
+ translator,
604
+ viewModel.errors
605
+ )
577
606
 
578
607
  // Filter our components based on their conditions using our evaluated state
579
608
  viewModel.components = this.filterConditionalComponents(
@@ -582,7 +611,10 @@ export class QuestionPageController extends PageController {
582
611
  evaluationState
583
612
  )
584
613
 
585
- return h.view(viewName, viewModel)
614
+ return h.view(viewName, {
615
+ ...viewModel,
616
+ t
617
+ })
586
618
  }
587
619
 
588
620
  // Save state
@@ -6,6 +6,7 @@ import Joi from 'joi'
6
6
 
7
7
  import { isRepeatState } from '../components/FormComponent.js'
8
8
  import { redirectPath } from '../helpers.js'
9
+ import { type Translator } from '../i18n/types.js'
9
10
  import { type FormModel } from '../models/index.js'
10
11
  import { QuestionPageController } from './QuestionPageController.js'
11
12
  import {
@@ -193,9 +194,20 @@ export class RepeatPageController extends QuestionPageController {
193
194
  return super.proceed(request, h, nextPath)
194
195
  }
195
196
 
196
- const viewModel = this.getListSummaryViewModel(request, context, list)
197
+ const translator = this.getTranslator(request)
198
+ const { t } = translator
197
199
 
198
- return h.view(this.listSummaryViewName, viewModel)
200
+ const viewModel = this.getListSummaryViewModel(
201
+ request,
202
+ context,
203
+ list,
204
+ translator
205
+ )
206
+
207
+ return h.view(this.listSummaryViewName, {
208
+ ...viewModel,
209
+ t
210
+ })
199
211
  }
200
212
  }
201
213
 
@@ -220,6 +232,9 @@ export class RepeatPageController extends QuestionPageController {
220
232
  return super.proceed(request, h, nextPath)
221
233
  }
222
234
 
235
+ const translator = this.getTranslator(request)
236
+ const { t } = translator
237
+
223
238
  const { action } = this.getFormParams(request)
224
239
 
225
240
  const hasErrorMin =
@@ -232,7 +247,6 @@ export class RepeatPageController extends QuestionPageController {
232
247
  // Show error if repeat limits apply
233
248
  if (hasErrorMin || hasErrorMax) {
234
249
  const count = hasErrorMax ? schema.max : schema.min
235
- const itemTitle = `answer${count === 1 ? '' : 's'}`
236
250
 
237
251
  context.errors = [
238
252
  {
@@ -240,14 +254,22 @@ export class RepeatPageController extends QuestionPageController {
240
254
  href: '',
241
255
  name: '',
242
256
  text: hasErrorMax
243
- ? `You can only add up to ${count} ${itemTitle}`
244
- : `You must add at least ${count} ${itemTitle}`
257
+ ? t('pages.repeater.tooMany', { count })
258
+ : t('pages.repeater.tooFew', { count })
245
259
  }
246
260
  ]
247
261
 
248
- const viewModel = this.getListSummaryViewModel(request, context, list)
262
+ const viewModel = this.getListSummaryViewModel(
263
+ request,
264
+ context,
265
+ list,
266
+ translator
267
+ )
249
268
 
250
- return h.view(this.listSummaryViewName, viewModel)
269
+ return h.view(this.listSummaryViewName, {
270
+ ...viewModel,
271
+ t
272
+ })
251
273
  }
252
274
 
253
275
  if (action === FormAction.AddAnother) {
@@ -281,11 +303,14 @@ export class RepeatPageController extends QuestionPageController {
281
303
  const itemId = this.getItemId(request)
282
304
  const item = this.getItemFromList(list, itemId)
283
305
 
306
+ const translator = this.getTranslator(request)
307
+ const { t } = translator
308
+
284
309
  if (!item || list.length === 1) {
285
310
  throw Boom.notFound(
286
311
  item
287
- ? 'Last list item cannot be removed'
288
- : 'List item to remove not found'
312
+ ? t('pages.repeater.lastItemCannotBeRemoved')
313
+ : t('pages.repeater.itemToRemoveNotFound')
289
314
  )
290
315
  }
291
316
 
@@ -294,11 +319,12 @@ export class RepeatPageController extends QuestionPageController {
294
319
  return h.view(this.listDeleteViewName, {
295
320
  ...viewModel,
296
321
  context,
297
- backLink: this.getBackLink(request, context),
298
- pageTitle: 'Are you sure you want to remove this answer?',
322
+ backLink: this.getBackLink(request, context, t),
323
+ pageTitle: t('pages.repeater.removeAnswer'),
299
324
  itemTitle: `${title} ${list.indexOf(item) + 1}`,
300
- buttonConfirm: { text: 'Remove' },
301
- buttonCancel: { text: 'Cancel' }
325
+ buttonConfirm: { text: t('pages.repeater.remove') },
326
+ buttonCancel: { text: t('pages.repeater.cancel') },
327
+ t
302
328
  } satisfies ItemDeletePageViewModel)
303
329
  }
304
330
  }
@@ -318,11 +344,13 @@ export class RepeatPageController extends QuestionPageController {
318
344
  const itemId = this.getItemId(request)
319
345
  const item = this.getItemFromList(list, itemId)
320
346
 
347
+ const { t } = this.getTranslator(request)
348
+
321
349
  if (!item || list.length === 1) {
322
350
  throw Boom.notFound(
323
351
  item
324
- ? 'Last list item cannot be removed'
325
- : 'List item to remove not found'
352
+ ? t('pages.repeater.lastItemCannotBeRemoved')
353
+ : t('pages.repeater.itemToRemoveNotFound')
326
354
  )
327
355
  }
328
356
 
@@ -343,17 +371,21 @@ export class RepeatPageController extends QuestionPageController {
343
371
 
344
372
  getViewModel(
345
373
  request: FormContextRequest,
346
- context: FormContext
374
+ context: FormContext,
375
+ translator: Translator
347
376
  ): FormPageViewModel {
348
377
  const { state } = context
378
+ const { tPage } = translator
349
379
 
350
380
  const list = this.getListFromState(state)
351
381
  const itemId = this.getItemId(request)
352
382
  const item = this.getItemFromList(list, itemId)
353
383
 
354
- const viewModel = super.getViewModel(request, context)
384
+ const viewModel = super.getViewModel(request, context, translator)
355
385
  const itemNumber = item ? list.indexOf(item) + 1 : list.length + 1
356
- const repeatCaption = `${this.repeat.options.title} ${itemNumber}`
386
+ const title =
387
+ tPage(this.pageDef, 'repeatTitle') || this.pageDef.repeat.options.title
388
+ const repeatCaption = `${title} ${itemNumber}`
357
389
 
358
390
  return {
359
391
  ...viewModel,
@@ -367,12 +399,15 @@ export class RepeatPageController extends QuestionPageController {
367
399
  getListSummaryViewModel(
368
400
  request: FormContextRequest,
369
401
  context: FormContext,
370
- list: RepeatListState
402
+ list: RepeatListState,
403
+ translator: Translator
371
404
  ): RepeaterSummaryPageViewModel {
372
405
  const { collection, href, repeat } = this
373
406
  const { query } = request
374
407
  const { isForceAccess, errors } = context
375
408
 
409
+ const { t } = translator
410
+
376
411
  const { title } = repeat.options
377
412
 
378
413
  const summaryList: SummaryList = {
@@ -396,9 +431,11 @@ export class RepeatPageController extends QuestionPageController {
396
431
  href: redirectPath(`${href}/${item.itemId}`, {
397
432
  returnUrl: query.returnUrl ?? this.getHref(summaryPath)
398
433
  }),
399
- text: 'Change',
434
+ text: t('pages.repeater.change'),
400
435
  classes: 'govuk-link--no-visited-state',
401
- visuallyHiddenText: `item ${index + 1}`
436
+ visuallyHiddenText: t('pages.repeater.visuallyHiddenItem', {
437
+ index: index + 1
438
+ })
402
439
  })
403
440
 
404
441
  if (count > 1) {
@@ -406,15 +443,17 @@ export class RepeatPageController extends QuestionPageController {
406
443
  href: redirectPath(`${href}/${item.itemId}/confirm-delete`, {
407
444
  returnUrl: query.returnUrl
408
445
  }),
409
- text: 'Remove',
446
+ text: t('pages.repeater.remove'),
410
447
  classes: 'govuk-link--no-visited-state',
411
- visuallyHiddenText: `item ${index + 1}`
448
+ visuallyHiddenText: t('pages.repeater.visuallyHiddenItem', {
449
+ index: index + 1
450
+ })
412
451
  })
413
452
  }
414
453
  }
415
454
 
416
455
  const itemDisplayText = collection.fields.length
417
- ? collection.fields[0].getDisplayStringFromState(item)
456
+ ? collection.fields[0].getDisplayStringFromState(item, translator)
418
457
  : ''
419
458
 
420
459
  summaryList.rows.push({
@@ -422,7 +461,7 @@ export class RepeatPageController extends QuestionPageController {
422
461
  text: `${title} ${index + 1}`
423
462
  },
424
463
  value: {
425
- text: itemDisplayText || 'Not provided'
464
+ text: itemDisplayText || t('pages.repeater.notProvided')
426
465
  },
427
466
  actions: {
428
467
  items
@@ -431,13 +470,11 @@ export class RepeatPageController extends QuestionPageController {
431
470
  })
432
471
  }
433
472
 
434
- const unit = count === 1 ? 'answer' : 'answers'
435
-
436
473
  return {
437
474
  ...this.viewModel,
438
- backLink: this.getBackLink(request, context),
475
+ backLink: this.getBackLink(request, context, t),
439
476
  repeatTitle: title,
440
- pageTitle: `You have added ${count} ${unit}`,
477
+ pageTitle: t('pages.repeater.pageTitle', { count }),
441
478
  showTitle: true,
442
479
  context,
443
480
  errors,
@@ -1,3 +1,4 @@
1
+ import { type Translator } from '../i18n/types.js'
1
2
  import { QuestionPageController } from './QuestionPageController.js'
2
3
  import { type FormContext } from '../types.js'
3
4
  import { type FormRequest } from '../../../routes/types.js'
@@ -11,9 +12,13 @@ export class StartPageController extends QuestionPageController {
11
12
 
12
13
  allowSaveAndExit = false
13
14
 
14
- getViewModel(request: FormRequest, context: FormContext) {
15
+ getViewModel(
16
+ request: FormRequest,
17
+ context: FormContext,
18
+ translator: Translator
19
+ ) {
15
20
  return {
16
- ...super.getViewModel(request, context),
21
+ ...super.getViewModel(request, context, translator),
17
22
  isStartPage: true
18
23
  }
19
24
  }
@@ -8,6 +8,7 @@ import {
8
8
  type FormRequest,
9
9
  type FormResponseToolkit
10
10
  } from '../../../routes/types.js'
11
+ import { resolveLanguage } from '../../../utils/utils.js'
11
12
 
12
13
  export class StatusPageController extends QuestionPageController {
13
14
  declare pageDef: PageStatus
@@ -32,6 +33,10 @@ export class StatusPageController extends QuestionPageController {
32
33
  ) => {
33
34
  const { viewModel, viewName } = this
34
35
 
36
+ const language = resolveLanguage(request)
37
+ const translator = this.model.createTranslator(language)
38
+ const { t, tForm } = translator
39
+
35
40
  const cacheService = getCacheService(request.server)
36
41
  const confirmationState = await cacheService.getConfirmationState(request)
37
42
 
@@ -55,10 +60,13 @@ export class StatusPageController extends QuestionPageController {
55
60
 
56
61
  return h.view(viewName, {
57
62
  ...viewModel,
58
- submissionGuidance,
59
63
  formName,
64
+ submissionGuidance,
60
65
  showReferenceNumber: this.showReferenceNumber,
61
- referenceNumber: confirmationState.referenceNumber
66
+ referenceNumber: confirmationState.referenceNumber,
67
+ t,
68
+ tForm,
69
+ context
62
70
  })
63
71
  }
64
72
  }
@@ -20,6 +20,7 @@ import {
20
20
  createError,
21
21
  getCacheService
22
22
  } from '../helpers.js'
23
+ import { type Translator } from '../i18n/types.js'
23
24
  import {
24
25
  SummaryViewModel,
25
26
  type FormModel
@@ -89,11 +90,13 @@ export class SummaryPageController extends QuestionPageController {
89
90
 
90
91
  getSummaryViewModel(
91
92
  request: FormContextRequest,
92
- context: FormContext
93
+ context: FormContext,
94
+ translator: Translator
93
95
  ): SummaryViewModel {
94
- const viewModel = new SummaryViewModel(request, this, context)
96
+ const { t } = translator
97
+
98
+ const viewModel = new SummaryViewModel(request, this, context, translator)
95
99
 
96
- const { query } = request
97
100
  const { payload, errors, state } = context
98
101
 
99
102
  const paymentField = this.findPaymentField()
@@ -110,7 +113,8 @@ export class SummaryPageController extends QuestionPageController {
110
113
  viewModel.paymentState = paymentState
111
114
  viewModel.paymentDetails = this.buildPaymentDetails(
112
115
  paymentField,
113
- paymentState
116
+ paymentState,
117
+ t
114
118
  )
115
119
  }
116
120
 
@@ -126,9 +130,13 @@ export class SummaryPageController extends QuestionPageController {
126
130
  }
127
131
  }
128
132
 
129
- const components = this.collection.getViewModel(payload, errors, query)
133
+ const components = this.collection.getViewModel({
134
+ payload,
135
+ errors,
136
+ translator
137
+ })
130
138
 
131
- viewModel.backLink = this.getBackLink(request, context)
139
+ viewModel.backLink = this.getBackLink(request, context, t)
132
140
  viewModel.feedbackLink = this.feedbackLink
133
141
  viewModel.phaseTag = this.phaseTag
134
142
  viewModel.components = components
@@ -142,32 +150,33 @@ export class SummaryPageController extends QuestionPageController {
142
150
  paymentField: PaymentField,
143
151
  paymentState: NonNullable<
144
152
  ReturnType<PaymentField['getPaymentStateFromState']>
145
- >
153
+ >,
154
+ t: (key: string, opts?: Record<string, unknown>) => string
146
155
  ) {
147
156
  const rows = [
148
157
  {
149
- key: { text: 'Payment for' },
158
+ key: { text: t('pages.summary.paymentFor') },
150
159
  value: { text: paymentState.description }
151
160
  },
152
161
  {
153
- key: { text: 'Total amount' },
162
+ key: { text: t('pages.summary.totalAmount') },
154
163
  value: { text: formatCurrency(paymentState.amount) }
155
164
  },
156
165
  {
157
- key: { text: 'Reference' },
166
+ key: { text: t('pages.summary.reference') },
158
167
  value: { text: paymentState.reference }
159
168
  }
160
169
  ]
161
170
 
162
171
  if (paymentState.preAuth?.createdAt) {
163
172
  rows.push({
164
- key: { text: 'Date of payment' },
173
+ key: { text: t('pages.summary.dateOfPayment') },
165
174
  value: { text: formatPaymentDate(paymentState.preAuth.createdAt) }
166
175
  })
167
176
  }
168
177
 
169
178
  return {
170
- title: { text: 'Payment details' },
179
+ title: { text: t('pages.summary.paymentDetailsTitle') },
171
180
  summaryList: { rows }
172
181
  }
173
182
  }
@@ -183,6 +192,9 @@ export class SummaryPageController extends QuestionPageController {
183
192
  ) => {
184
193
  const { viewName } = this
185
194
 
195
+ const translator = this.getTranslator(request)
196
+ const { t } = translator
197
+
186
198
  // After GOV.UK Pay callback, auto-submit the form instead of
187
199
  // showing CYA again. The payment is already pre-authorized.
188
200
  if (request.query.paymentComplete === 'true') {
@@ -195,11 +207,12 @@ export class SummaryPageController extends QuestionPageController {
195
207
 
196
208
  await this.reconcilePaymentState(request, context)
197
209
 
198
- const viewModel = this.getSummaryViewModel(request, context)
210
+ const viewModel = this.getSummaryViewModel(request, context, translator)
199
211
 
200
212
  viewModel.hasMissingNotificationEmail =
201
213
  await this.hasMissingNotificationEmail(request, context)
202
214
 
215
+ viewModel.t = t
203
216
  return h.view(viewName, viewModel)
204
217
  }
205
218
  }
@@ -270,7 +283,8 @@ export class SummaryPageController extends QuestionPageController {
270
283
  checkEmailAddressForLiveFormSubmission(notificationEmail, isPreview)
271
284
 
272
285
  if (notificationEmail) {
273
- const viewModel = this.getSummaryViewModel(request, context)
286
+ const translator = this.getTranslator(request)
287
+ const viewModel = this.getSummaryViewModel(request, context, translator)
274
288
 
275
289
  try {
276
290
  await submitForm(
@@ -279,7 +293,8 @@ export class SummaryPageController extends QuestionPageController {
279
293
  request,
280
294
  viewModel,
281
295
  model,
282
- notificationEmail
296
+ notificationEmail,
297
+ translator
283
298
  )
284
299
  } catch (error) {
285
300
  return this.handleSubmissionError(error, request, h)
@@ -388,12 +403,17 @@ export class SummaryPageController extends QuestionPageController {
388
403
  request: FormRequestPayload,
389
404
  h: FormResponseToolkit
390
405
  ) {
406
+ const { t } = this.getTranslator(request)
407
+
391
408
  const helpUrl = error.helpLink ?? DEFAULT_PAYMENT_HELP_URL
392
- const helpLinkHtml = ` or you can <a href="${helpUrl}" target="_blank" rel="noopener noreferrer" class="govuk-link">contact us (opens in new tab)</a> and quote your reference number to arrange a refund`
409
+ const contactUsLink = `<a href="${helpUrl}" target="_blank" rel="noopener noreferrer" class="govuk-link">${t('pages.summary.contactUsLinkText')}</a>`
410
+ const helpLinkHtml = t('pages.summary.submissionFailedContactSuffix', {
411
+ contactUsLink
412
+ })
393
413
 
394
414
  const govukError = createError(
395
415
  'submission',
396
- `There was a problem and your form was not submitted. Try submitting the form again${helpLinkHtml}.`
416
+ `${t('pages.summary.submissionFailed')}${helpLinkHtml}.`
397
417
  )
398
418
 
399
419
  request.yar.flash(COMPONENT_STATE_ERROR, govukError, true)
@@ -420,7 +440,8 @@ export async function submitForm(
420
440
  request: FormRequestPayload,
421
441
  summaryViewModel: SummaryViewModel,
422
442
  model: FormModel,
423
- emailAddress: string
443
+ emailAddress: string,
444
+ translator: Translator
424
445
  ) {
425
446
  await finaliseComponents(request, formMetadata, context, model)
426
447
 
@@ -434,6 +455,7 @@ export async function submitForm(
434
455
  const items = getFormSubmissionData(
435
456
  summaryViewModel.context,
436
457
  summaryViewModel.details,
458
+ translator,
437
459
  model
438
460
  )
439
461
 
@@ -444,6 +466,7 @@ export async function submitForm(
444
466
  items,
445
467
  emailAddress,
446
468
  request.yar.id,
469
+ translator,
447
470
  summaryViewModel.context.referenceNumber
448
471
  )
449
472
 
@@ -523,6 +546,7 @@ function submitData(
523
546
  items: DetailItem[],
524
547
  retrievalKey: string,
525
548
  sessionId: string,
549
+ translator: Translator,
526
550
  referenceNumber: string
527
551
  ) {
528
552
  const { formSubmissionService } = model.services
@@ -532,8 +556,8 @@ function submitData(
532
556
  sessionId,
533
557
  retrievalKey,
534
558
  referenceNumber,
535
- main: buildMainRecords(items),
536
- repeaters: buildRepeaterRecords(items)
559
+ main: buildMainRecords(items, translator),
560
+ repeaters: buildRepeaterRecords(items, translator)
537
561
  }
538
562
  return submit(payload)
539
563
  }
@@ -541,6 +565,7 @@ function submitData(
541
565
  export function getFormSubmissionData(
542
566
  context: FormContext,
543
567
  details: Detail[],
568
+ translator: Translator,
544
569
  model: FormModel
545
570
  ) {
546
571
  const items = context.relevantPages
@@ -551,7 +576,7 @@ export function getFormSubmissionData(
551
576
  )
552
577
  .flat()
553
578
 
554
- const paymentItems = getPaymentFieldItems(context, model)
579
+ const paymentItems = getPaymentFieldItems(context, translator, model)
555
580
 
556
581
  return [...items, ...paymentItems]
557
582
  }
@@ -562,6 +587,7 @@ export function getFormSubmissionData(
562
587
  */
563
588
  function getPaymentFieldItems(
564
589
  context: FormContext,
590
+ translator: Translator,
565
591
  model: FormModel
566
592
  ): DetailItemField[] {
567
593
  const items: DetailItemField[] = []
@@ -577,7 +603,7 @@ function getPaymentFieldItems(
577
603
  field,
578
604
  state: context.state,
579
605
  href: page.href,
580
- value: field.getDisplayStringFromState(context.state)
606
+ value: field.getDisplayStringFromState(context.state, translator)
581
607
  })
582
608
  }
583
609
  }