@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
@@ -0,0 +1,28 @@
1
+ import { t as resolveKey } from '../../i18n/index.js'
2
+ import { type Translator } from '../../i18n/types.js'
3
+
4
+ /**
5
+ * Shared Translator stub for tests where translation content is not the focus.
6
+ * Uses the real English i18n keys so tests that assert on English text still pass.
7
+ * Each tX function resolves the entity's property via the real English t() so
8
+ * i18n key constants (e.g. 'components.yesNoField.yes') resolve to their English
9
+ * values ("Yes") rather than being returned verbatim.
10
+ */
11
+ function resolveEntity(entity: unknown, prop: string): string {
12
+ if (typeof entity !== 'object' || entity === null) return ''
13
+ const raw =
14
+ ((entity as Record<string, unknown>)[prop] as string | undefined) ?? ''
15
+ if (!raw) return ''
16
+ return resolveKey(raw, 'en-GB') || raw
17
+ }
18
+
19
+ export const stubTranslator: Translator = {
20
+ t: (key: string, opts?: Record<string, unknown>) =>
21
+ resolveKey(key, 'en-GB', opts),
22
+ tForm: (prop) => resolveEntity({}, prop),
23
+ tPage: (entity, prop) => resolveEntity(entity, prop as string),
24
+ tComponent: (entity, prop) => resolveEntity(entity, prop as string),
25
+ tSection: (entity, prop) => resolveEntity(entity, prop as string),
26
+ tListItem: (entity, prop) => resolveEntity(entity, prop as string),
27
+ language: 'en-GB'
28
+ }
@@ -65,12 +65,14 @@ export class PaymentSubmissionError extends Error {
65
65
  static checkPaymentAmount(
66
66
  stateAmount: number,
67
67
  expectedAmount: number | undefined,
68
- component: FormComponent
68
+ component: FormComponent,
69
+ t: (key: string) => string
69
70
  ) {
70
71
  if (stateAmount / 100 !== expectedAmount) {
72
+ const message = t('components.paymentField.paymentAmountMismatch')
71
73
  throw new PaymentPreAuthError(
72
74
  component,
73
- 'The pre-authorised payment amount is somehow different from that requested. Try adding payment details again.',
75
+ message,
74
76
  true,
75
77
  PaymentErrorTypes.PaymentIncomplete
76
78
  )
@@ -3,6 +3,7 @@ import { type SubmitPayload } from '@defra/forms-model'
3
3
  import { GeospatialField } from '../../components/GeospatialField.js'
4
4
  import { PaymentField } from '../../components/PaymentField.js'
5
5
  import { getAnswer } from '../../components/helpers/components.js'
6
+ import { type Translator } from '../../i18n/types.js'
6
7
  import {
7
8
  type DetailItem,
8
9
  type DetailItemField
@@ -23,7 +24,10 @@ export interface SubmitRecord {
23
24
  * Regular fields are converted to single records, while PaymentField
24
25
  * components are expanded into four separate records.
25
26
  */
26
- export function buildMainRecords(items: DetailItem[]): SubmitRecord[] {
27
+ export function buildMainRecords(
28
+ items: DetailItem[],
29
+ translator: Translator
30
+ ): SubmitRecord[] {
27
31
  const fieldItems = items.filter(
28
32
  (item): item is DetailItemField => 'field' in item
29
33
  )
@@ -46,7 +50,7 @@ export function buildMainRecords(items: DetailItem[]): SubmitRecord[] {
46
50
  records.push({
47
51
  name: item.name,
48
52
  title: item.label,
49
- value: getAnswer(item.field, item.state, { format: 'data' })
53
+ value: getAnswer(item.field, item.state, translator, { format: 'data' })
50
54
  })
51
55
  }
52
56
  }
@@ -102,7 +106,8 @@ export function buildPaymentRecords(item: DetailItemField): SubmitRecord[] {
102
106
  * Builds the repeater submission records from repeater items.
103
107
  */
104
108
  export function buildRepeaterRecords(
105
- items: DetailItem[]
109
+ items: DetailItem[],
110
+ translator: Translator
106
111
  ): SubmitPayload['repeaters'] {
107
112
  return items
108
113
  .filter((item) => 'subItems' in item)
@@ -119,7 +124,9 @@ export function buildRepeaterRecords(
119
124
  const formValue = subItem.field.getFormValueFromState(subItem.state)
120
125
  value = formValue === undefined ? '' : JSON.stringify(formValue)
121
126
  } else {
122
- value = getAnswer(subItem.field, subItem.state, { format: 'data' })
127
+ value = getAnswer(subItem.field, subItem.state, translator, {
128
+ format: 'data'
129
+ })
123
130
  }
124
131
 
125
132
  return {
@@ -1,7 +1,6 @@
1
1
  // Declaration above is needed for: https://github.com/hapijs/joi/issues/3064
2
2
 
3
- import joi, {
4
- type JoiExpression,
3
+ import {
5
4
  type LanguageMessages,
6
5
  type LanguageMessagesExt,
7
6
  type ReferenceOptions,
@@ -9,6 +8,11 @@ import joi, {
9
8
  } from 'joi'
10
9
 
11
10
  import { lowerFirstPreserveProperNouns } from '../components/helpers/index.js'
11
+ import {
12
+ buildValidationMessages,
13
+ type ValidationMessages
14
+ } from '../i18n/buildValidationMessages.js'
15
+ import { t } from '../i18n/index.js'
12
16
 
13
17
  export const opts = {
14
18
  functions: {
@@ -17,58 +21,13 @@ export const opts = {
17
21
  } as ReferenceOptions
18
22
 
19
23
  /**
20
- * see @link https://joi.dev/api/?v=17.4.2#template-syntax for template syntax
24
+ * Module-level English message templates — built via the same factory used per-form.
25
+ * Components that have not yet been migrated to use model.validationMessages still
26
+ * import messageTemplate directly and get the English version.
21
27
  */
22
- export const messageTemplate: Record<string, JoiExpression> = {
23
- declarationRequired: joi.expression(
24
- 'You must confirm you understand and agree with the {{lowerFirst(#label)}} to continue',
25
- opts
26
- ) as JoiExpression,
27
- required: joi.expression(
28
- 'Enter {{lowerFirst(#label)}}',
29
- opts
30
- ) as JoiExpression,
31
- selectRequired: joi.expression(
32
- 'Select {{lowerFirst(#label)}}',
33
- opts
34
- ) as JoiExpression,
35
- selectYesNoRequired: '{{#label}} - select yes or no',
36
- max: '{{#label}} must be {{#limit}} characters or less',
37
- min: '{{#label}} must be {{#limit}} characters or more',
38
- minMax: '{{#label}} must be between {{#min}} and {{#max}} characters',
39
- pattern: joi.expression(
40
- 'Enter a valid {{lowerFirst(#label)}}',
41
- opts
42
- ) as JoiExpression,
43
- format: joi.expression(
44
- 'Enter {{lowerFirst(#label)}} in the correct format',
45
- opts
46
- ) as JoiExpression,
47
- unicode: '{{#label}} includes invalid characters, for example, long dashes',
48
- number: '{{#label}} must be a number',
49
- numberPrecision: '{{#label}} must have {{#limit}} or fewer decimal places',
50
- numberInteger: '{{#label}} must be a whole number',
51
- numberMin: '{{#label}} must be {{#limit}} or higher',
52
- numberMax: '{{#label}} must be {{#limit}} or lower',
53
- maxWords: '{{#label}} must be {{#limit}} words or fewer',
54
-
55
- // Nested fields use component title
56
-
57
- objectRequired: joi.expression('Enter {{#label}}', opts) as JoiExpression,
58
- objectMissing: joi.expression(
59
- '{{#title}} must include a {{lowerFirst(#label)}}',
60
- opts
61
- ) as JoiExpression,
62
- dateFormat: '{{#title}} must be a real date',
63
- dateMin: '{{#title}} must be the same as or after {{#limit}}',
64
- dateMax: '{{#title}} must be the same as or before {{#limit}}',
65
- arrayMin: 'Select at least {{#limit}} options from the list',
66
- arrayMax: 'Only {{#limit}} can be selected from the list',
67
- arrayLength: 'Select only {{#limit}} options from the list',
68
- featuresMin: 'Define at least {{#limit}} features',
69
- featuresMax: 'Only {{#limit}} features can be defined',
70
- featuresLength: 'Define exactly {{#limit}} features'
71
- }
28
+ export const messageTemplate: ValidationMessages = buildValidationMessages(
29
+ (key) => t(key, 'en-GB')
30
+ )
72
31
 
73
32
  export const messages: LanguageMessagesExt = {
74
33
  'string.base': messageTemplate.required,
@@ -105,6 +64,37 @@ export const messages: LanguageMessagesExt = {
105
64
  export const messagesPre: LanguageMessages =
106
65
  messages as unknown as LanguageMessages
107
66
 
67
+ export function buildLanguageMessages(
68
+ t: (key: string) => string
69
+ ): LanguageMessages {
70
+ const vm = buildValidationMessages(t)
71
+ return {
72
+ 'string.base': vm.required,
73
+ 'string.min': vm.min,
74
+ 'string.empty': vm.required,
75
+ 'string.max': vm.max,
76
+ 'string.email': vm.format,
77
+ 'string.pattern.base': vm.pattern,
78
+ 'string.maxWords': vm.maxWords,
79
+ 'number.base': vm.number,
80
+ 'number.precision': vm.numberPrecision,
81
+ 'number.integer': vm.numberInteger,
82
+ 'number.unsafe': vm.format,
83
+ 'number.min': vm.numberMin,
84
+ 'number.max': vm.numberMax,
85
+ 'object.required': vm.objectRequired,
86
+ 'object.and': vm.objectMissing,
87
+ 'any.only': vm.selectRequired,
88
+ 'any.required': vm.selectRequired,
89
+ 'any.empty': vm.required,
90
+ 'date.base': vm.dateFormat,
91
+ 'date.format': vm.dateFormat,
92
+ 'date.min': vm.dateMin,
93
+ 'date.max': vm.dateMax,
94
+ 'object.invalidjson': vm.format
95
+ } as unknown as LanguageMessages
96
+ }
97
+
108
98
  export const validationOptions: ValidationOptions = {
109
99
  abortEarly: false,
110
100
  messages: messagesPre,
@@ -36,6 +36,7 @@ export const plugin = {
36
36
  model,
37
37
  cache,
38
38
  saveAndExit,
39
+ getLanguage,
39
40
  nunjucks: nunjucksOptions,
40
41
  viewContext,
41
42
  preparePageEventRequestOptions,
@@ -78,6 +79,7 @@ export const plugin = {
78
79
  server.expose('viewContext', viewContext)
79
80
  server.expose('cacheService', cacheService)
80
81
  server.expose('saveAndExit', saveAndExit)
82
+ server.expose('getLanguage', getLanguage)
81
83
  server.expose('baseUrl', baseUrl)
82
84
  server.expose('services', services)
83
85
 
@@ -43,6 +43,7 @@ import {
43
43
  type FormRequest,
44
44
  type FormResponseToolkit
45
45
  } from '../../../routes/types.js'
46
+ import { resolveLanguage } from '../../../utils/utils.js'
46
47
 
47
48
  export async function redirectOrMakeHandler(
48
49
  request: AnyFormRequest,
@@ -82,7 +83,14 @@ export async function redirectOrMakeHandler(
82
83
  state = await importExternalComponentState(request, page, state)
83
84
 
84
85
  const flash = cacheService.getFlash(request)
85
- const context = model.getFormContext(request, state, flash?.errors)
86
+ const language = resolveLanguage(request)
87
+ const translator = model.createTranslator(language)
88
+ const context = model.getFormContext(
89
+ request,
90
+ state,
91
+ flash?.errors,
92
+ translator
93
+ )
86
94
 
87
95
  await copyNotYetValidatedState(request, context)
88
96
 
@@ -44,6 +44,7 @@ import {
44
44
  stateSchema
45
45
  } from '../../../schemas/index.js'
46
46
  import * as httpService from '../../../services/httpService.js'
47
+ import { resolveLanguage } from '../../../utils/utils.js'
47
48
 
48
49
  async function handleHttpEvent(
49
50
  request: AnyFormRequest,
@@ -58,10 +59,13 @@ async function handleHttpEvent(
58
59
 
59
60
  // TODO: Update structured data POST payload with when helper
60
61
  // is updated to removing the dependency on `SummaryViewModel` etc.
61
- const viewModel = new SummaryViewModel(request, page, context)
62
+ const language = resolveLanguage(request)
63
+ const translator = model.createTranslator(language)
64
+ const viewModel = new SummaryViewModel(request, page, context, translator)
62
65
  const items = getFormSubmissionData(
63
66
  viewModel.context,
64
67
  viewModel.details,
68
+ translator,
65
69
  model
66
70
  )
67
71
 
@@ -94,3 +94,8 @@ export type {
94
94
 
95
95
  export * from './schema.js'
96
96
  export { FormAdapterSubmissionSchemaVersion } from './enums.js'
97
+
98
+ export type {
99
+ FormDefinitionTranslations,
100
+ Translator
101
+ } from '../i18n/types.js'
@@ -32,6 +32,7 @@ export const formAdapterSubmissionMessageMetaSchema =
32
32
  isPreview: Joi.boolean().required(),
33
33
  notificationEmail: notificationEmailAddressSchema.required(),
34
34
  versionMetadata: formVersionMetadataSchema.optional(),
35
+ language: Joi.string().optional(),
35
36
  custom: Joi.object()
36
37
  .pattern(/^/, Joi.any())
37
38
  .unknown()
@@ -11,8 +11,10 @@ import {
11
11
  import {
12
12
  type PluginProperties,
13
13
  type Request,
14
+ type RequestQuery,
14
15
  type ResponseObject
15
16
  } from '@hapi/hapi'
17
+ import { type Yar } from '@hapi/yar'
16
18
  import { type JoiExpression, type ValidationErrorItem } from 'joi'
17
19
 
18
20
  import { FormComponent } from './components/FormComponent.js'
@@ -31,6 +33,7 @@ import {
31
33
  type LatLongState,
32
34
  type MonthYearState
33
35
  } from './components/types.js'
36
+ import { type Translator } from './i18n/types.js'
34
37
  import { type FormModel } from './models/index.js'
35
38
  import { type DetailItemField } from './models/types.js'
36
39
  import { type PageController } from './pageControllers/PageController.js'
@@ -199,6 +202,8 @@ export interface FormContext {
199
202
  pageMap: Map<string, PageControllerClass>
200
203
  componentMap: Map<string, Component>
201
204
  referenceNumber: string
205
+ languages: { name: string; code: string }[]
206
+ translator: Translator | undefined
202
207
  }
203
208
 
204
209
  export type FormContextRequest = (
@@ -394,6 +399,7 @@ export interface PageViewModelBase extends Partial<ViewContext> {
394
399
  feedbackLink?: string
395
400
  serviceUrl: string
396
401
  phaseTag?: string
402
+ t?: (key: string, opts?: Record<string, unknown>) => string
397
403
  }
398
404
 
399
405
  export interface ItemDeletePageViewModel extends PageViewModelBase {
@@ -471,6 +477,8 @@ export type SaveAndExitHandler = (
471
477
  context: FormContext
472
478
  ) => ResponseObject
473
479
 
480
+ export type GetLanguageHandler = (query?: RequestQuery, yar?: Yar) => string
481
+
474
482
  export interface ExternalArgs {
475
483
  component: ComponentDef
476
484
  controller: QuestionPageController
@@ -510,6 +518,7 @@ export interface PluginOptions {
510
518
  viewContext: PluginProperties['forms-engine-plugin']['viewContext']
511
519
  preparePageEventRequestOptions?: PreparePageEventRequestOptions
512
520
  onRequest?: OnRequestCallback
521
+ getLanguage?: GetLanguageHandler
513
522
  baseUrl: string // base URL of the application, protocol and hostname e.g. "https://myapp.com"
514
523
  ordnanceSurveyApiKey?: string
515
524
  ordnanceSurveyApiSecret?: string
@@ -526,6 +535,7 @@ export interface FormAdapterSubmissionMessageMeta {
526
535
  isPreview: boolean
527
536
  notificationEmail: string
528
537
  versionMetadata?: FormVersionMetadata
538
+ language?: string
529
539
  custom?: Record<string, unknown>
530
540
  }
531
541
 
@@ -61,7 +61,7 @@
61
61
  {% set detailsHtml %}
62
62
  {% if component.model.instructionText %}
63
63
  {{ govukDetails({
64
- summaryText: "How to find location details",
64
+ summaryText: t('components.locationFieldBase.howToFind'),
65
65
  html: component.model.instructionText | markdown | safe,
66
66
  classes: "govuk-!-margin-top-3"
67
67
  }) }}
@@ -70,7 +70,9 @@
70
70
 
71
71
  {% set hasErrors = showFieldsetError and component.model.errorMessage %}
72
72
 
73
- <div class="govuk-form-group app-location-field {{ "govuk-form-group--error" if hasErrors }}" data-locationtype="{{component.type | lower}}">
73
+ <div class="govuk-form-group app-location-field {{ "govuk-form-group--error" if hasErrors }}"
74
+ data-locationtype="{{component.type | lower}}"
75
+ data-maplayers="{{component.model.mapLayers}}">
74
76
  {{ govukFieldset({
75
77
  legend: {
76
78
  text: component.model.fieldset.legend.text,
@@ -4,9 +4,9 @@
4
4
  {% set upload = component.model.upload %}
5
5
 
6
6
  <div id="uploadedFilesContainer">
7
- <h2 class="govuk-heading-m">Uploaded files</h2>
7
+ <h2 class="govuk-heading-m">{{ t('components.fileUploadField.uploadedFilesHeading') }}</h2>
8
8
  {% if upload.count %}
9
- <p class="govuk-body" role="alert">{{upload.count}} file{{ "s" if upload.count > 1}} uploaded</p>
9
+ <p class="govuk-body" role="alert">{{ t('components.fileUploadField.filesCount', { count: upload.count }) }}</p>
10
10
  <p class="govuk-body">
11
11
  </p>
12
12
 
@@ -14,7 +14,7 @@
14
14
  {{ govukSummaryList(upload.summaryList) }}
15
15
  {% endif %}
16
16
  {% else %}
17
- <p class="govuk-body">{{upload.count}} files uploaded</p>
17
+ <p class="govuk-body">{{ t('components.fileUploadField.filesCount', { count: upload.count }) }}</p>
18
18
  {% endif %}
19
19
  </div>
20
20
  {% endmacro %}
@@ -1,7 +1,10 @@
1
1
  {% from "govuk/components/textarea/macro.njk" import govukTextarea %}
2
2
 
3
3
  {% macro GeospatialField(component) %}
4
- <div class="app-geospatial-field" data-country="{{component.model.country}}" data-geometryTypes="{{component.model.geometryTypes}}">
4
+ <div class="app-geospatial-field"
5
+ data-country="{{component.model.country}}"
6
+ data-geometryTypes="{{component.model.geometryTypes}}"
7
+ data-maplayers="{{component.model.mapLayers}}">
5
8
  {{ govukTextarea(component.model) }}
6
9
  </div>
7
10
  {% endmacro %}
@@ -8,7 +8,7 @@
8
8
 
9
9
  {% if component.model.instructionText %}
10
10
  {{ govukDetails({
11
- summaryText: "How to find location details",
11
+ summaryText: t('components.nationalGridField.howToFind'),
12
12
  html: component.model.instructionText | markdown | safe,
13
13
  classes: "govuk-!-margin-top-3"
14
14
  }) }}
@@ -10,7 +10,7 @@
10
10
 
11
11
  {% if component.model.instructionText %}
12
12
  {{ govukDetails({
13
- summaryText: "How to find location details",
13
+ summaryText: t('components.osGridRefField.howToFind'),
14
14
  html: component.model.instructionText | markdown | safe,
15
15
  classes: "govuk-!-margin-top-3"
16
16
  }) }}
@@ -11,27 +11,27 @@
11
11
  <div class="app-payment-field">
12
12
  {% if isPreAuthorised %}
13
13
  {# Payment already pre-authorised - show confirmation message #}
14
- <h2 class="govuk-heading-m">You have already authorised a payment for this form</h2>
14
+ <h2 class="govuk-heading-m">{{ t('components.paymentField.preAuthorisedTitle') }}</h2>
15
15
 
16
- <p class="govuk-body">Continue to submit the form. You will not be charged twice.</p>
16
+ <p class="govuk-body">{{ t('components.paymentField.preAuthorisedBody') }}</p>
17
17
  {% else %}
18
18
  {# No pre-authorisation - show payment form #}
19
- <h2 class="govuk-heading-m">{{ model.label.text if model.label and model.label.text else "Payment details required" }}</h2>
19
+ <h2 class="govuk-heading-m">{{ model.label.text if model.label and model.label.text else t('components.paymentField.detailsRequired') }}</h2>
20
20
 
21
21
  <p class="govuk-body">{{ description }}</p>
22
22
 
23
23
  {{ govukWarningText({
24
- text: "You may see a pending transaction in your bank account but you will only be charged when you submit the form.",
25
- iconFallbackText: "Warning"
24
+ text: t('components.paymentField.pendingTransaction'),
25
+ iconFallbackText: t('common.warningIconFallback')
26
26
  }) }}
27
27
 
28
- <p class="govuk-body">You can submit the form after you have added your payment details.</p>
28
+ <p class="govuk-body">{{ t('components.paymentField.canSubmitAfterPayment') }}</p>
29
29
 
30
- <p class="govuk-body govuk-!-margin-bottom-1">Total amount:</p>
30
+ <p class="govuk-body govuk-!-margin-bottom-1">{{ t('components.paymentField.totalAmountLabel') }}</p>
31
31
  <p class="govuk-heading-l govuk-!-margin-bottom-4 govuk-!-padding-top-0">{{ amount }}</p>
32
32
 
33
33
  {{ govukButton({
34
- text: "Add payment details",
34
+ text: t('components.paymentField.addPaymentDetails'),
35
35
  attributes: {
36
36
  name: "action",
37
37
  value: "external-" + model.name
@@ -37,13 +37,13 @@
37
37
 
38
38
  {% if value %}
39
39
  {% set insetHtml %}
40
- <strong>Selected address:</strong>
40
+ <strong>{{ t('components.addressField.selectedAddress') }}</strong>
41
41
  <br><br>
42
42
  {{ value }}
43
43
  <br><br>
44
44
  <p class="govuk-body">
45
45
  <button class="govuk-link govuk-button--link govuk-!-margin-right-1" name="action"
46
- value="external-{{component.model.name}}">Use a different address</button>
46
+ value="external-{{component.model.name}}">{{ t('components.addressField.useDifferentAddress') }}</button>
47
47
  </p>
48
48
  {% endset %}
49
49
 
@@ -54,14 +54,14 @@
54
54
  {% else %}
55
55
  <div class="govuk-button-group govuk-!-margin-bottom-0">
56
56
  {{ govukButton({
57
- text: "Find an address",
57
+ text: t('components.addressField.findAddress'),
58
58
  attributes: {
59
59
  name: "action",
60
60
  value: "external-" + component.model.name
61
61
  },
62
62
  classes: "govuk-button--secondary govuk-!-margin-right-1 govuk-!-margin-bottom-0"
63
63
  }) }}
64
- <p class="govuk-body govuk-!-margin-bottom-0">or <button class="govuk-link govuk-button--link govuk-!-margin-right-1 govuk-!-margin-bottom-0" name="action" value="external-{{component.model.name}}--step:manual">enter address manually</button></p>
64
+ <p class="govuk-body govuk-!-margin-bottom-0">or <button class="govuk-link govuk-button--link govuk-!-margin-right-1 govuk-!-margin-bottom-0" name="action" value="external-{{component.model.name}}--step:manual">{{ t('components.addressField.enterManually') }}</button></p>
65
65
  </div>
66
66
  {# Include a line break if this is the last component #}
67
67
  {% if components[components.length - 1] == component %}
@@ -8,16 +8,16 @@
8
8
  <div class="govuk-grid-row">
9
9
  <div class="govuk-grid-column-two-thirds">
10
10
  {{ govukPanel({
11
- titleText: pageTitle,
12
- html: "Your reference number<br><strong>" + referenceNumber + "</strong>" if showReferenceNumber
11
+ titleText: t('pages.confirmation.formSubmitted'),
12
+ html: t('pages.confirmation.referenceNumber') + "<br><strong>" + referenceNumber + "</strong>" if showReferenceNumber
13
13
  }) }}
14
- <h2 class="govuk-heading-m">What happens next</h2>
14
+ <h2 class="govuk-heading-m">{{ t('pages.confirmation.whatHappensNext') }}</h2>
15
15
  <div class="app-prose-scope">
16
16
  {{ submissionGuidance | markdown(3) | safe }}
17
17
  </div>
18
18
  {% if feedbackLink %}
19
19
  <p class="govuk-body">
20
- <a href="{{ feedbackLink }}" class="govuk-link govuk-link--no-visited-state">What do you think of this service?</a> (takes 30 seconds)
20
+ <a href="{{ feedbackLink }}" class="govuk-link govuk-link--no-visited-state">{{ t('pages.confirmation.feedbackLink') }}</a>
21
21
  </p>
22
22
  {% endif %}
23
23
  </div>
@@ -9,17 +9,17 @@
9
9
  <div class="govuk-grid-row">
10
10
  <div class="govuk-grid-column-two-thirds">
11
11
  {{ govukPanel({
12
- titleText: pageTitle or "Your progress has been saved"
12
+ titleText: pageTitle or t('pages.exit.defaultTitle')
13
13
  }) }}
14
14
 
15
- <h2 class="govuk-heading-m">What happens next</h2>
15
+ <h2 class="govuk-heading-m">{{ t('pages.exit.whatHappensNext') }}</h2>
16
16
  <div class="app-prose-scope">
17
- <p class="govuk-body">Your form progress has been saved. You can return to complete your application at any time using the link provided.</p>
17
+ <p class="govuk-body">{{ t('pages.exit.body') }}</p>
18
18
 
19
19
  {% if returnUrl %}
20
20
  <p class="govuk-body">
21
21
  {{ govukButton({
22
- text: "Return to application",
22
+ text: t('pages.exit.returnToApplication'),
23
23
  href: returnUrl,
24
24
  classes: "govuk-button--secondary"
25
25
  }) }}
@@ -14,15 +14,15 @@
14
14
 
15
15
  {% if formAction %}
16
16
  {{ govukButton({
17
- text: "Upload file",
17
+ text: t('pages.fileUpload.upload'),
18
18
  classes: "govuk-button--secondary upload-file-button",
19
19
  preventDoubleClick: true,
20
20
  disabled: context.isForceAccess
21
21
  }) }}
22
22
  {% else %}
23
23
  {{ govukWarningText({
24
- text: "You have reached the maximum number of files. Please remove a file to upload more.",
25
- iconFallbackText: "Warning"
24
+ text: t('pages.fileUpload.maxFilesReached'),
25
+ iconFallbackText: t('common.warningIconFallback')
26
26
  }) }}
27
27
  {% endif %}
28
28
  </form>
@@ -13,14 +13,14 @@
13
13
 
14
14
  {% if showPaymentExpiredNotification %}
15
15
  {{ govukNotificationBanner({
16
- titleText: "Important",
17
- html: '<h3 class="govuk-notification-banner__heading">Your payment has been cancelled</h3><p class="govuk-body">Your payment details were deleted because the form was inactive for 5 days.</p><p class="govuk-body">Add your payment details again.</p>'
16
+ titleText: t('pages.question.paymentCancelledBannerTitle'),
17
+ html: '<h3 class="govuk-notification-banner__heading">' + t('pages.question.paymentCancelledTitle') + '</h3><p class="govuk-body">' + t('pages.question.paymentCancelledBody') + '</p><p class="govuk-body">' + t('pages.question.paymentCancelledAction') + '</p>'
18
18
  }) }}
19
19
  {% endif %}
20
20
 
21
21
  {% if errors | length and not showPaymentExpiredNotification %}
22
22
  {{ govukErrorSummary({
23
- titleText: "There is a problem",
23
+ titleText: t('errors.title'),
24
24
  errorList: checkErrorTemplates(errors)
25
25
  }) }}
26
26
  {% endif %}
@@ -13,7 +13,7 @@
13
13
 
14
14
  {% if errors %}
15
15
  {{ govukErrorSummary({
16
- titleText: "There is a problem",
16
+ titleText: t('errors.title'),
17
17
  errorList: errors
18
18
  }) }}
19
19
  {% endif %}
@@ -20,11 +20,11 @@
20
20
  {{ componentList(components) }}
21
21
 
22
22
  {% if isStartPage %}
23
- {% set buttonText = "Start now" %}
23
+ {% set buttonText = t('pages.question.startNow') %}
24
24
  {% elif submitButtonText %}
25
25
  {% set buttonText = submitButtonText %}
26
26
  {% else %}
27
- {% set buttonText = "Continue" %}
27
+ {% set buttonText = t('common.continue') %}
28
28
  {% endif %}
29
29
 
30
30
  <div class="govuk-button-group">
@@ -38,7 +38,7 @@
38
38
 
39
39
  {% if allowSaveAndExit %}
40
40
  {{ govukButton({
41
- text: "Save and exit",
41
+ text: t('common.saveAndExit'),
42
42
  classes: "govuk-button--secondary",
43
43
  name: "action",
44
44
  value: "save-and-exit",