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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (309) hide show
  1. package/.server/server/forms/register-as-a-unicorn-breeder.yaml +0 -14
  2. package/.server/server/forms/simple-form.yaml +106 -3
  3. package/.server/server/plugins/engine/components/AutocompleteField.d.ts +11 -11
  4. package/.server/server/plugins/engine/components/AutocompleteField.js +2 -2
  5. package/.server/server/plugins/engine/components/AutocompleteField.js.map +1 -1
  6. package/.server/server/plugins/engine/components/CheckboxesField.d.ts +3 -2
  7. package/.server/server/plugins/engine/components/CheckboxesField.js +4 -9
  8. package/.server/server/plugins/engine/components/CheckboxesField.js.map +1 -1
  9. package/.server/server/plugins/engine/components/ComponentCollection.d.ts +8 -7
  10. package/.server/server/plugins/engine/components/ComponentCollection.js +106 -51
  11. package/.server/server/plugins/engine/components/ComponentCollection.js.map +1 -1
  12. package/.server/server/plugins/engine/components/DatePartsField.d.ts +8 -6
  13. package/.server/server/plugins/engine/components/DatePartsField.js +27 -9
  14. package/.server/server/plugins/engine/components/DatePartsField.js.map +1 -1
  15. package/.server/server/plugins/engine/components/DeclarationField.d.ts +13 -11
  16. package/.server/server/plugins/engine/components/DeclarationField.js +31 -9
  17. package/.server/server/plugins/engine/components/DeclarationField.js.map +1 -1
  18. package/.server/server/plugins/engine/components/EastingNorthingField.d.ts +6 -5
  19. package/.server/server/plugins/engine/components/EastingNorthingField.js +42 -22
  20. package/.server/server/plugins/engine/components/EastingNorthingField.js.map +1 -1
  21. package/.server/server/plugins/engine/components/EmailAddressField.d.ts +11 -14
  22. package/.server/server/plugins/engine/components/EmailAddressField.js +2 -2
  23. package/.server/server/plugins/engine/components/EmailAddressField.js.map +1 -1
  24. package/.server/server/plugins/engine/components/FileUploadField.d.ts +14 -12
  25. package/.server/server/plugins/engine/components/FileUploadField.js +22 -12
  26. package/.server/server/plugins/engine/components/FileUploadField.js.map +1 -1
  27. package/.server/server/plugins/engine/components/FormComponent.d.ts +21 -12
  28. package/.server/server/plugins/engine/components/FormComponent.js +33 -14
  29. package/.server/server/plugins/engine/components/FormComponent.js.map +1 -1
  30. package/.server/server/plugins/engine/components/GeospatialField.d.ts +14 -12
  31. package/.server/server/plugins/engine/components/GeospatialField.js +19 -13
  32. package/.server/server/plugins/engine/components/GeospatialField.js.map +1 -1
  33. package/.server/server/plugins/engine/components/LatLongField.d.ts +6 -5
  34. package/.server/server/plugins/engine/components/LatLongField.js +32 -20
  35. package/.server/server/plugins/engine/components/LatLongField.js.map +1 -1
  36. package/.server/server/plugins/engine/components/ListFormComponent.d.ts +7 -6
  37. package/.server/server/plugins/engine/components/ListFormComponent.js +19 -7
  38. package/.server/server/plugins/engine/components/ListFormComponent.js.map +1 -1
  39. package/.server/server/plugins/engine/components/LocationFieldBase.d.ts +17 -16
  40. package/.server/server/plugins/engine/components/LocationFieldBase.js +2 -2
  41. package/.server/server/plugins/engine/components/LocationFieldBase.js.map +1 -1
  42. package/.server/server/plugins/engine/components/LocationFieldHelpers.d.ts +3 -3
  43. package/.server/server/plugins/engine/components/LocationFieldHelpers.js +2 -2
  44. package/.server/server/plugins/engine/components/LocationFieldHelpers.js.map +1 -1
  45. package/.server/server/plugins/engine/components/Markdown.d.ts +8 -7
  46. package/.server/server/plugins/engine/components/Markdown.js +5 -2
  47. package/.server/server/plugins/engine/components/Markdown.js.map +1 -1
  48. package/.server/server/plugins/engine/components/MonthYearField.d.ts +9 -7
  49. package/.server/server/plugins/engine/components/MonthYearField.js +26 -8
  50. package/.server/server/plugins/engine/components/MonthYearField.js.map +1 -1
  51. package/.server/server/plugins/engine/components/MultilineTextField.d.ts +10 -9
  52. package/.server/server/plugins/engine/components/MultilineTextField.js +2 -2
  53. package/.server/server/plugins/engine/components/MultilineTextField.js.map +1 -1
  54. package/.server/server/plugins/engine/components/NationalGridFieldNumberField.d.ts +2 -1
  55. package/.server/server/plugins/engine/components/NationalGridFieldNumberField.js +14 -6
  56. package/.server/server/plugins/engine/components/NationalGridFieldNumberField.js.map +1 -1
  57. package/.server/server/plugins/engine/components/NumberField.d.ts +10 -9
  58. package/.server/server/plugins/engine/components/NumberField.js +2 -2
  59. package/.server/server/plugins/engine/components/NumberField.js.map +1 -1
  60. package/.server/server/plugins/engine/components/OsGridRefField.d.ts +2 -1
  61. package/.server/server/plugins/engine/components/OsGridRefField.js +14 -6
  62. package/.server/server/plugins/engine/components/OsGridRefField.js.map +1 -1
  63. package/.server/server/plugins/engine/components/PaymentField.d.ts +12 -10
  64. package/.server/server/plugins/engine/components/PaymentField.js +21 -8
  65. package/.server/server/plugins/engine/components/PaymentField.js.map +1 -1
  66. package/.server/server/plugins/engine/components/SelectField.d.ts +11 -11
  67. package/.server/server/plugins/engine/components/SelectField.js +2 -2
  68. package/.server/server/plugins/engine/components/SelectField.js.map +1 -1
  69. package/.server/server/plugins/engine/components/SelectionControlField.d.ts +4 -4
  70. package/.server/server/plugins/engine/components/SelectionControlField.js +2 -2
  71. package/.server/server/plugins/engine/components/SelectionControlField.js.map +1 -1
  72. package/.server/server/plugins/engine/components/TelephoneNumberField.d.ts +10 -9
  73. package/.server/server/plugins/engine/components/TelephoneNumberField.js +2 -2
  74. package/.server/server/plugins/engine/components/TelephoneNumberField.js.map +1 -1
  75. package/.server/server/plugins/engine/components/UkAddressField.d.ts +12 -10
  76. package/.server/server/plugins/engine/components/UkAddressField.js +29 -17
  77. package/.server/server/plugins/engine/components/UkAddressField.js.map +1 -1
  78. package/.server/server/plugins/engine/components/YesNoField.d.ts +3 -0
  79. package/.server/server/plugins/engine/components/YesNoField.js +9 -0
  80. package/.server/server/plugins/engine/components/YesNoField.js.map +1 -1
  81. package/.server/server/plugins/engine/components/helpers/components.d.ts +3 -2
  82. package/.server/server/plugins/engine/components/helpers/components.js +11 -8
  83. package/.server/server/plugins/engine/components/helpers/components.js.map +1 -1
  84. package/.server/server/plugins/engine/components/types.d.ts +8 -1
  85. package/.server/server/plugins/engine/components/types.js.map +1 -1
  86. package/.server/server/plugins/engine/configureEnginePlugin.js +8 -1
  87. package/.server/server/plugins/engine/configureEnginePlugin.js.map +1 -1
  88. package/.server/server/plugins/engine/form-context.d.ts +1 -0
  89. package/.server/server/plugins/engine/form-context.js +4 -2
  90. package/.server/server/plugins/engine/form-context.js.map +1 -1
  91. package/.server/server/plugins/engine/helpers.d.ts +1 -1
  92. package/.server/server/plugins/engine/helpers.js +8 -13
  93. package/.server/server/plugins/engine/helpers.js.map +1 -1
  94. package/.server/server/plugins/engine/i18n/buildValidationMessages.d.ts +39 -0
  95. package/.server/server/plugins/engine/i18n/buildValidationMessages.js +50 -0
  96. package/.server/server/plugins/engine/i18n/buildValidationMessages.js.map +1 -0
  97. package/.server/server/plugins/engine/i18n/createFormTranslator.d.ts +5 -0
  98. package/.server/server/plugins/engine/i18n/createFormTranslator.js +18 -0
  99. package/.server/server/plugins/engine/i18n/createFormTranslator.js.map +1 -0
  100. package/.server/server/plugins/engine/i18n/createTranslator.d.ts +9 -0
  101. package/.server/server/plugins/engine/i18n/createTranslator.js +51 -0
  102. package/.server/server/plugins/engine/i18n/createTranslator.js.map +1 -0
  103. package/.server/server/plugins/engine/i18n/extractBaseTranslations.d.ts +5 -0
  104. package/.server/server/plugins/engine/i18n/extractBaseTranslations.js +57 -0
  105. package/.server/server/plugins/engine/i18n/extractBaseTranslations.js.map +1 -0
  106. package/.server/server/plugins/engine/i18n/index.d.ts +18 -0
  107. package/.server/server/plugins/engine/i18n/index.js +71 -0
  108. package/.server/server/plugins/engine/i18n/index.js.map +1 -0
  109. package/.server/server/plugins/engine/i18n/translations/cy.json +271 -0
  110. package/.server/server/plugins/engine/i18n/translations/en-GB.json +271 -0
  111. package/.server/server/plugins/engine/i18n/types.d.ts +41 -0
  112. package/.server/server/plugins/engine/i18n/types.js +2 -0
  113. package/.server/server/plugins/engine/i18n/types.js.map +1 -0
  114. package/.server/server/plugins/engine/index.js +3 -2
  115. package/.server/server/plugins/engine/index.js.map +1 -1
  116. package/.server/server/plugins/engine/models/FormModel.d.ts +9 -1
  117. package/.server/server/plugins/engine/models/FormModel.js +44 -18
  118. package/.server/server/plugins/engine/models/FormModel.js.map +1 -1
  119. package/.server/server/plugins/engine/models/SummaryViewModel.d.ts +5 -2
  120. package/.server/server/plugins/engine/models/SummaryViewModel.js +44 -18
  121. package/.server/server/plugins/engine/models/SummaryViewModel.js.map +1 -1
  122. package/.server/server/plugins/engine/options.js +2 -1
  123. package/.server/server/plugins/engine/options.js.map +1 -1
  124. package/.server/server/plugins/engine/outputFormatters/adapter/v1.js +4 -0
  125. package/.server/server/plugins/engine/outputFormatters/adapter/v1.js.map +1 -1
  126. package/.server/server/plugins/engine/outputFormatters/human/v1.js +2 -1
  127. package/.server/server/plugins/engine/outputFormatters/human/v1.js.map +1 -1
  128. package/.server/server/plugins/engine/outputFormatters/machine/v1.js +7 -6
  129. package/.server/server/plugins/engine/outputFormatters/machine/v1.js.map +1 -1
  130. package/.server/server/plugins/engine/pageControllers/FileUploadPageController.d.ts +2 -1
  131. package/.server/server/plugins/engine/pageControllers/FileUploadPageController.js +6 -3
  132. package/.server/server/plugins/engine/pageControllers/FileUploadPageController.js.map +1 -1
  133. package/.server/server/plugins/engine/pageControllers/PageController.d.ts +3 -1
  134. package/.server/server/plugins/engine/pageControllers/PageController.js +11 -1
  135. package/.server/server/plugins/engine/pageControllers/PageController.js.map +1 -1
  136. package/.server/server/plugins/engine/pageControllers/QuestionPageController.d.ts +4 -2
  137. package/.server/server/plugins/engine/pageControllers/QuestionPageController.js +52 -21
  138. package/.server/server/plugins/engine/pageControllers/QuestionPageController.js.map +1 -1
  139. package/.server/server/plugins/engine/pageControllers/RepeatPageController.d.ts +3 -2
  140. package/.server/server/plugins/engine/pageControllers/RepeatPageController.js +63 -26
  141. package/.server/server/plugins/engine/pageControllers/RepeatPageController.js.map +1 -1
  142. package/.server/server/plugins/engine/pageControllers/StartPageController.d.ts +3 -1
  143. package/.server/server/plugins/engine/pageControllers/StartPageController.js +2 -2
  144. package/.server/server/plugins/engine/pageControllers/StartPageController.js.map +1 -1
  145. package/.server/server/plugins/engine/pageControllers/StatusPageController.js +12 -2
  146. package/.server/server/plugins/engine/pageControllers/StatusPageController.js.map +1 -1
  147. package/.server/server/plugins/engine/pageControllers/SummaryPageController.d.ts +4 -3
  148. package/.server/server/plugins/engine/pageControllers/SummaryPageController.js +45 -28
  149. package/.server/server/plugins/engine/pageControllers/SummaryPageController.js.map +1 -1
  150. package/.server/server/plugins/engine/pageControllers/__stubs__/translator.d.ts +2 -0
  151. package/.server/server/plugins/engine/pageControllers/__stubs__/translator.js +24 -0
  152. package/.server/server/plugins/engine/pageControllers/__stubs__/translator.js.map +1 -0
  153. package/.server/server/plugins/engine/pageControllers/errors.d.ts +1 -1
  154. package/.server/server/plugins/engine/pageControllers/errors.js +3 -2
  155. package/.server/server/plugins/engine/pageControllers/errors.js.map +1 -1
  156. package/.server/server/plugins/engine/pageControllers/helpers/submission.d.ts +3 -2
  157. package/.server/server/plugins/engine/pageControllers/helpers/submission.js +4 -4
  158. package/.server/server/plugins/engine/pageControllers/helpers/submission.js.map +1 -1
  159. package/.server/server/plugins/engine/pageControllers/validationOptions.d.ts +7 -3
  160. package/.server/server/plugins/engine/pageControllers/validationOptions.js +34 -33
  161. package/.server/server/plugins/engine/pageControllers/validationOptions.js.map +1 -1
  162. package/.server/server/plugins/engine/plugin.js +2 -0
  163. package/.server/server/plugins/engine/plugin.js.map +1 -1
  164. package/.server/server/plugins/engine/routes/index.js +4 -1
  165. package/.server/server/plugins/engine/routes/index.js.map +1 -1
  166. package/.server/server/plugins/engine/routes/questions.js +5 -2
  167. package/.server/server/plugins/engine/routes/questions.js.map +1 -1
  168. package/.server/server/plugins/engine/types/index.d.ts +1 -0
  169. package/.server/server/plugins/engine/types/index.js.map +1 -1
  170. package/.server/server/plugins/engine/types/schema.js +1 -0
  171. package/.server/server/plugins/engine/types/schema.js.map +1 -1
  172. package/.server/server/plugins/engine/types.d.ts +12 -1
  173. package/.server/server/plugins/engine/types.js.map +1 -1
  174. package/.server/server/plugins/engine/views/components/_location-field-base.html +1 -1
  175. package/.server/server/plugins/engine/views/components/fileuploadfield.html +3 -3
  176. package/.server/server/plugins/engine/views/components/nationalgridfieldnumberfield.html +1 -1
  177. package/.server/server/plugins/engine/views/components/osgridreffield.html +1 -1
  178. package/.server/server/plugins/engine/views/components/paymentfield.html +8 -8
  179. package/.server/server/plugins/engine/views/components/ukaddressfield.html +4 -4
  180. package/.server/server/plugins/engine/views/confirmation.html +4 -4
  181. package/.server/server/plugins/engine/views/exit.html +4 -4
  182. package/.server/server/plugins/engine/views/file-upload.html +3 -3
  183. package/.server/server/plugins/engine/views/index.html +3 -3
  184. package/.server/server/plugins/engine/views/item-delete.html +1 -1
  185. package/.server/server/plugins/engine/views/partials/form.html +3 -3
  186. package/.server/server/plugins/engine/views/partials/preview-banner.html +4 -4
  187. package/.server/server/plugins/engine/views/partials/warn-missing-notification-email.html +4 -5
  188. package/.server/server/plugins/engine/views/repeat-list-summary.html +4 -4
  189. package/.server/server/plugins/engine/views/summary.html +14 -7
  190. package/.server/server/plugins/nunjucks/enviroment.test.js +10 -0
  191. package/.server/server/plugins/nunjucks/enviroment.test.js.map +1 -1
  192. package/.server/server/plugins/nunjucks/environment.d.ts +8 -0
  193. package/.server/server/plugins/nunjucks/environment.js +13 -0
  194. package/.server/server/plugins/nunjucks/environment.js.map +1 -1
  195. package/.server/server/plugins/nunjucks/filters/answer.js +9 -1
  196. package/.server/server/plugins/nunjucks/filters/answer.js.map +1 -1
  197. package/.server/server/plugins/nunjucks/filters/answer.test.js +13 -2
  198. package/.server/server/plugins/nunjucks/filters/answer.test.js.map +1 -1
  199. package/.server/server/plugins/nunjucks/filters/field.d.ts +1 -1
  200. package/.server/server/plugins/postcode-lookup/models/index.d.ts +24 -19
  201. package/.server/server/plugins/postcode-lookup/models/index.js +83 -76
  202. package/.server/server/plugins/postcode-lookup/models/index.js.map +1 -1
  203. package/.server/server/plugins/postcode-lookup/routes/index.js +7 -13
  204. package/.server/server/plugins/postcode-lookup/routes/index.js.map +1 -1
  205. package/.server/server/plugins/postcode-lookup/types.d.ts +1 -0
  206. package/.server/server/plugins/postcode-lookup/types.js +1 -0
  207. package/.server/server/plugins/postcode-lookup/types.js.map +1 -1
  208. package/.server/server/plugins/postcode-lookup/views/postcode-lookup-details.html +3 -3
  209. package/.server/server/types.d.ts +2 -1
  210. package/.server/server/types.js.map +1 -1
  211. package/.server/server/utils/utils.d.ts +5 -0
  212. package/.server/server/utils/utils.js +16 -0
  213. package/.server/server/utils/utils.js.map +1 -1
  214. package/.server/typings/hapi/index.d.js.map +1 -1
  215. package/package.json +3 -2
  216. package/src/server/forms/register-as-a-unicorn-breeder.yaml +0 -14
  217. package/src/server/forms/simple-form.yaml +106 -3
  218. package/src/server/plugins/engine/components/AutocompleteField.ts +3 -6
  219. package/src/server/plugins/engine/components/CheckboxesField.ts +12 -11
  220. package/src/server/plugins/engine/components/ComponentCollection.ts +143 -61
  221. package/src/server/plugins/engine/components/DatePartsField.ts +33 -11
  222. package/src/server/plugins/engine/components/DeclarationField.ts +37 -14
  223. package/src/server/plugins/engine/components/EastingNorthingField.ts +83 -22
  224. package/src/server/plugins/engine/components/EmailAddressField.ts +4 -7
  225. package/src/server/plugins/engine/components/FileUploadField.ts +28 -22
  226. package/src/server/plugins/engine/components/FormComponent.ts +49 -12
  227. package/src/server/plugins/engine/components/GeospatialField.ts +36 -21
  228. package/src/server/plugins/engine/components/LatLongField.ts +52 -21
  229. package/src/server/plugins/engine/components/ListFormComponent.ts +26 -10
  230. package/src/server/plugins/engine/components/LocationFieldBase.ts +5 -8
  231. package/src/server/plugins/engine/components/LocationFieldHelpers.ts +3 -3
  232. package/src/server/plugins/engine/components/Markdown.ts +7 -3
  233. package/src/server/plugins/engine/components/MonthYearField.ts +32 -10
  234. package/src/server/plugins/engine/components/MultilineTextField.ts +5 -8
  235. package/src/server/plugins/engine/components/NationalGridFieldNumberField.ts +25 -11
  236. package/src/server/plugins/engine/components/NumberField.ts +3 -4
  237. package/src/server/plugins/engine/components/OsGridRefField.ts +25 -9
  238. package/src/server/plugins/engine/components/PaymentField.ts +22 -12
  239. package/src/server/plugins/engine/components/SelectField.ts +3 -6
  240. package/src/server/plugins/engine/components/SelectionControlField.ts +7 -8
  241. package/src/server/plugins/engine/components/TelephoneNumberField.ts +4 -7
  242. package/src/server/plugins/engine/components/UkAddressField.ts +33 -18
  243. package/src/server/plugins/engine/components/YesNoField.ts +10 -0
  244. package/src/server/plugins/engine/components/helpers/components.ts +13 -6
  245. package/src/server/plugins/engine/components/types.ts +9 -0
  246. package/src/server/plugins/engine/configureEnginePlugin.ts +12 -1
  247. package/src/server/plugins/engine/form-context.ts +8 -2
  248. package/src/server/plugins/engine/helpers.ts +10 -18
  249. package/src/server/plugins/engine/i18n/buildValidationMessages.ts +69 -0
  250. package/src/server/plugins/engine/i18n/createFormTranslator.ts +33 -0
  251. package/src/server/plugins/engine/i18n/createTranslator.ts +61 -0
  252. package/src/server/plugins/engine/i18n/extractBaseTranslations.ts +61 -0
  253. package/src/server/plugins/engine/i18n/index.ts +80 -0
  254. package/src/server/plugins/engine/i18n/translations/cy.json +271 -0
  255. package/src/server/plugins/engine/i18n/translations/en-GB.json +271 -0
  256. package/src/server/plugins/engine/i18n/types.ts +62 -0
  257. package/src/server/plugins/engine/index.ts +4 -2
  258. package/src/server/plugins/engine/models/FormModel.ts +59 -23
  259. package/src/server/plugins/engine/models/SummaryViewModel.ts +68 -25
  260. package/src/server/plugins/engine/options.js +2 -1
  261. package/src/server/plugins/engine/outputFormatters/adapter/v1.ts +5 -0
  262. package/src/server/plugins/engine/outputFormatters/human/v1.ts +2 -3
  263. package/src/server/plugins/engine/outputFormatters/machine/v1.ts +9 -8
  264. package/src/server/plugins/engine/pageControllers/FileUploadPageController.ts +7 -3
  265. package/src/server/plugins/engine/pageControllers/PageController.ts +12 -1
  266. package/src/server/plugins/engine/pageControllers/QuestionPageController.ts +53 -21
  267. package/src/server/plugins/engine/pageControllers/RepeatPageController.ts +66 -29
  268. package/src/server/plugins/engine/pageControllers/StartPageController.ts +7 -2
  269. package/src/server/plugins/engine/pageControllers/StatusPageController.ts +10 -2
  270. package/src/server/plugins/engine/pageControllers/SummaryPageController.ts +53 -24
  271. package/src/server/plugins/engine/pageControllers/__stubs__/translator.ts +28 -0
  272. package/src/server/plugins/engine/pageControllers/errors.ts +4 -2
  273. package/src/server/plugins/engine/pageControllers/helpers/submission.ts +11 -4
  274. package/src/server/plugins/engine/pageControllers/validationOptions.ts +43 -53
  275. package/src/server/plugins/engine/plugin.ts +2 -0
  276. package/src/server/plugins/engine/routes/index.ts +9 -1
  277. package/src/server/plugins/engine/routes/questions.ts +5 -1
  278. package/src/server/plugins/engine/types/index.ts +5 -0
  279. package/src/server/plugins/engine/types/schema.ts +1 -0
  280. package/src/server/plugins/engine/types.ts +10 -0
  281. package/src/server/plugins/engine/views/components/_location-field-base.html +1 -1
  282. package/src/server/plugins/engine/views/components/fileuploadfield.html +3 -3
  283. package/src/server/plugins/engine/views/components/nationalgridfieldnumberfield.html +1 -1
  284. package/src/server/plugins/engine/views/components/osgridreffield.html +1 -1
  285. package/src/server/plugins/engine/views/components/paymentfield.html +8 -8
  286. package/src/server/plugins/engine/views/components/ukaddressfield.html +4 -4
  287. package/src/server/plugins/engine/views/confirmation.html +4 -4
  288. package/src/server/plugins/engine/views/exit.html +4 -4
  289. package/src/server/plugins/engine/views/file-upload.html +3 -3
  290. package/src/server/plugins/engine/views/index.html +3 -3
  291. package/src/server/plugins/engine/views/item-delete.html +1 -1
  292. package/src/server/plugins/engine/views/partials/form.html +3 -3
  293. package/src/server/plugins/engine/views/partials/preview-banner.html +4 -4
  294. package/src/server/plugins/engine/views/partials/warn-missing-notification-email.html +4 -5
  295. package/src/server/plugins/engine/views/repeat-list-summary.html +4 -4
  296. package/src/server/plugins/engine/views/summary.html +14 -7
  297. package/src/server/plugins/nunjucks/environment.js +14 -0
  298. package/src/server/plugins/nunjucks/filters/answer.js +12 -1
  299. package/src/server/plugins/postcode-lookup/models/index.js +144 -87
  300. package/src/server/plugins/postcode-lookup/routes/index.js +13 -16
  301. package/src/server/plugins/postcode-lookup/types.js +1 -0
  302. package/src/server/plugins/postcode-lookup/views/postcode-lookup-details.html +3 -3
  303. package/src/server/types.ts +2 -0
  304. package/src/server/utils/utils.js +14 -0
  305. package/src/typings/hapi/index.d.ts +1 -0
  306. package/.server/server/plugins/engine/components/constants.d.ts +0 -1
  307. package/.server/server/plugins/engine/components/constants.js +0 -2
  308. package/.server/server/plugins/engine/components/constants.js.map +0 -1
  309. package/src/server/plugins/engine/components/constants.ts +0 -1
@@ -1,4 +1,8 @@
1
- import { SchemaVersion, type Section } from '@defra/forms-model'
1
+ import {
2
+ SchemaVersion,
3
+ type ComponentDef,
4
+ type Section
5
+ } from '@defra/forms-model'
2
6
 
3
7
  import { PaymentField } from '../components/PaymentField.js'
4
8
  import { type PaymentState } from '../components/PaymentField.types.js'
@@ -15,6 +19,7 @@ import {
15
19
  getError,
16
20
  getPageHref
17
21
  } from '../helpers.js'
22
+ import { type Translator } from '../i18n/types.js'
18
23
  import {
19
24
  type Detail,
20
25
  type DetailItem,
@@ -56,22 +61,29 @@ export class SummaryViewModel {
56
61
  allowSaveAndExit = false
57
62
  paymentState?: PaymentState
58
63
  paymentDetails?: CheckAnswers
64
+ t: (key: string, opts?: Record<string, unknown>) => string
65
+ private readonly _translator!: Translator
59
66
  paymentRequired?: boolean
60
67
  paymentPreAuthorized?: boolean
61
68
 
62
69
  constructor(
63
70
  request: FormContextRequest,
64
71
  page: PageControllerClass,
65
- context: FormContext
72
+ context: FormContext,
73
+ translator: Translator
66
74
  ) {
67
75
  const { model } = page
68
76
  const { basePath, def, sections } = model
69
77
  const { isForceAccess } = context
70
78
 
79
+ const { t } = translator
80
+ this.t = t
81
+ this._translator = translator
82
+
71
83
  this.page = page
72
84
  this.pageTitle = page.title
73
85
  if (def.schema === SchemaVersion.V2 && !page.title) {
74
- this.pageTitle = 'Check your answers before sending your form'
86
+ this.pageTitle = t('pages.summary.title')
75
87
  }
76
88
 
77
89
  this.serviceUrl = `/${basePath}`
@@ -85,7 +97,7 @@ export class SummaryViewModel {
85
97
 
86
98
  // Format errors
87
99
  this.errors = result.error?.details.map(getError)
88
- this.details = this.summaryDetails(request, sections)
100
+ this.details = this.summaryDetails(request, sections, translator)
89
101
 
90
102
  // Format check answers
91
103
  this.checkAnswers = this.details.map((detail): CheckAnswers => {
@@ -98,7 +110,7 @@ export class SummaryViewModel {
98
110
  if (!isForceAccess) {
99
111
  items.push({
100
112
  href: item.href,
101
- text: 'Change',
113
+ text: t('pages.summary.change'),
102
114
  classes: 'govuk-link--no-visited-state',
103
115
  visuallyHiddenText: item.label
104
116
  })
@@ -110,7 +122,7 @@ export class SummaryViewModel {
110
122
  },
111
123
  value: {
112
124
  classes: 'app-prose-scope',
113
- html: item.value || 'Not provided'
125
+ html: item.value || t('pages.summary.notProvided')
114
126
  },
115
127
  actions: {
116
128
  items
@@ -125,7 +137,11 @@ export class SummaryViewModel {
125
137
  })
126
138
  }
127
139
 
128
- private summaryDetails(request: FormContextRequest, sections: Section[]) {
140
+ private summaryDetails(
141
+ request: FormContextRequest,
142
+ sections: Section[],
143
+ translator: Translator
144
+ ) {
129
145
  const { context, errors } = this
130
146
  const { relevantPages, state } = context
131
147
 
@@ -143,10 +159,15 @@ export class SummaryViewModel {
143
159
 
144
160
  if (page instanceof RepeatPageController) {
145
161
  items.push(
146
- ItemRepeat(page, state, {
147
- path: page.getSummaryPath(request),
148
- errors
149
- })
162
+ ItemRepeat(
163
+ page,
164
+ state,
165
+ {
166
+ path: page.getSummaryPath(request),
167
+ errors
168
+ },
169
+ translator
170
+ )
150
171
  )
151
172
  } else {
152
173
  for (const field of collection.fields) {
@@ -154,15 +175,20 @@ export class SummaryViewModel {
154
175
  if (field instanceof PaymentField) {
155
176
  continue
156
177
  }
157
- items.push(ItemField(page, state, field, { path, errors }))
178
+ items.push(
179
+ ItemField(page, state, field, { path, errors }, translator)
180
+ )
158
181
  }
159
182
  }
160
183
  })
161
184
 
162
185
  if (items.length) {
186
+ const sectionTitle = section
187
+ ? translator.tSection(section, 'title') || section.title
188
+ : undefined
163
189
  details.push({
164
190
  name: section?.name,
165
- title: section?.title,
191
+ title: sectionTitle,
166
192
  items
167
193
  })
168
194
  }
@@ -182,19 +208,22 @@ function ItemRepeat(
182
208
  options: {
183
209
  path: string
184
210
  errors?: FormSubmissionError[]
185
- }
211
+ },
212
+ translator: Translator
186
213
  ): DetailItemRepeat {
187
214
  const { collection, repeat } = page
188
215
  const { name, title } = repeat.options
189
216
 
190
217
  const values = page.getListFromState(state)
191
- const unit = values.length === 1 ? 'answer' : 'answers'
218
+ const count = values.length
219
+ const value =
220
+ count === 0 ? '' : translator.t('pages.repeater.pageTitle', { count })
192
221
 
193
222
  return {
194
223
  name,
195
224
  label: title,
196
225
  title,
197
- value: values.length ? `You have added ${values.length} ${unit}` : '',
226
+ value,
198
227
  href: getPageHref(page, options.path, {
199
228
  returnUrl: getPageHref(page, page.getSummaryPath())
200
229
  }),
@@ -204,7 +233,7 @@ function ItemRepeat(
204
233
  // Repeater field detail items
205
234
  subItems: values.map((repeatState) =>
206
235
  collection.fields.map((field) =>
207
- ItemField(page, repeatState, field, options)
236
+ ItemField(page, repeatState, field, options, translator)
208
237
  )
209
238
  )
210
239
  }
@@ -221,17 +250,31 @@ export function ItemField(
221
250
  options: {
222
251
  path: string
223
252
  errors?: FormSubmissionError[]
224
- }
253
+ },
254
+ translator: Translator
225
255
  ): DetailItemField {
256
+ // FormComponent doesn't expose shortDescription/title as raw def properties,
257
+ // so build a lookup object with English values to let tComponent's GUID lookup fire.
258
+ const fieldDef = {
259
+ id: field.id,
260
+ type: field.type,
261
+ shortDescription: field.label,
262
+ title: field.title
263
+ } as unknown as ComponentDef
264
+ const rawLabel = translator.tComponent(fieldDef, 'shortDescription')
265
+ const translatedLabel = rawLabel !== '' ? rawLabel : field.label
266
+ const rawTitle = translator.tComponent(fieldDef, 'title')
267
+ const translatedTitle = rawTitle !== '' ? rawTitle : field.title
268
+ const optional =
269
+ field.options.required === false
270
+ ? ` ${translator.t('common.optional')}`
271
+ : ''
226
272
  return {
227
273
  name: field.name,
228
- label: field.title,
229
- title:
230
- field.options.required === false
231
- ? `${field.summaryLabel} (optional)`
232
- : field.summaryLabel,
233
- error: field.getFirstError(options.errors),
234
- value: getAnswer(field, state),
274
+ label: translatedTitle,
275
+ title: `${translatedLabel}${optional}`,
276
+ error: field.getFirstError(translator, options.errors),
277
+ value: getAnswer(field, state, translator, { format: 'summary' }),
235
278
  href: getPageHref(page, options.path, {
236
279
  returnUrl: getPageHref(page, page.getSummaryPath())
237
280
  }),
@@ -25,7 +25,8 @@ const pluginRegistrationOptionsSchema = Joi.object({
25
25
  baseUrl: Joi.string().uri().required(),
26
26
  saveAndExit: Joi.function().optional(),
27
27
  ordnanceSurveyApiKey: Joi.string().optional(),
28
- ordnanceSurveyApiSecret: Joi.string().optional()
28
+ ordnanceSurveyApiSecret: Joi.string().optional(),
29
+ getLanguage: Joi.function().optional()
29
30
  })
30
31
 
31
32
  /**
@@ -49,6 +49,11 @@ export function format(
49
49
  meta.versionMetadata = versionMetadata
50
50
  }
51
51
 
52
+ const definitionLanguage = model.def.metadata?.language
53
+ if (typeof definitionLanguage === 'string') {
54
+ meta.language = definitionLanguage
55
+ }
56
+
52
57
  const main = Object.fromEntries(
53
58
  Object.entries(v2Main).map(([key, value]) => {
54
59
  if (value === undefined) {
@@ -30,6 +30,7 @@ export function format(
30
30
  formStatus: ReturnType<typeof checkFormStatus>,
31
31
  _formMetadata?: FormMetadata
32
32
  ) {
33
+ const translator = model.createTranslator()
33
34
  const { files } = submitResponse.result
34
35
 
35
36
  const formName = escapeMarkdown(model.name)
@@ -72,9 +73,7 @@ export function format(
72
73
  lines.push(`[${filename}](${designerUrl}/file-download/${fileId})\n`)
73
74
  } else {
74
75
  lines.push(
75
- getAnswer(item.field, item.state, {
76
- format: 'email'
77
- })
76
+ getAnswer(item.field, item.state, translator, { format: 'email' })
78
77
  )
79
78
  }
80
79
 
@@ -7,6 +7,7 @@ import { config } from '../../../../../config/index.js'
7
7
  import { getAnswer } from '../../components/helpers/components.js'
8
8
  import { FileUploadField } from '../../components/index.js'
9
9
  import { type checkFormStatus } from '../../helpers.js'
10
+ import { type Translator } from '../../i18n/types.js'
10
11
  import { type FormModel } from '../../models/index.js'
11
12
  import {
12
13
  type DetailItem,
@@ -25,9 +26,10 @@ export function format(
25
26
  _formStatus: ReturnType<typeof checkFormStatus>,
26
27
  _formMetadata?: FormMetadata
27
28
  ) {
29
+ const translator = model.createTranslator()
28
30
  const now = new Date()
29
31
 
30
- const categorisedData = categoriseData(items)
32
+ const categorisedData = categoriseData(items, translator)
31
33
 
32
34
  const data = {
33
35
  meta: {
@@ -68,7 +70,7 @@ export function format(
68
70
  * }
69
71
  * }
70
72
  */
71
- function categoriseData(items: DetailItem[]) {
73
+ function categoriseData(items: DetailItem[], translator: Translator) {
72
74
  const output: {
73
75
  main: Record<string, string>
74
76
  repeaters: Record<string, Record<string, string>[]>
@@ -77,11 +79,11 @@ function categoriseData(items: DetailItem[]) {
77
79
 
78
80
  items.forEach((item) => {
79
81
  if ('subItems' in item) {
80
- output.repeaters[item.name] = extractRepeaters(item)
82
+ output.repeaters[item.name] = extractRepeaters(item, translator)
81
83
  } else if (isFileUploadFieldItem(item)) {
82
84
  output.files[item.name] = extractFileUploads(item)
83
85
  } else {
84
- output.main[item.name] = getAnswer(item.field, item.state, {
86
+ output.main[item.name] = getAnswer(item.field, item.state, translator, {
85
87
  format: 'data'
86
88
  })
87
89
  }
@@ -95,7 +97,7 @@ function categoriseData(items: DetailItem[]) {
95
97
  * @param item - the repeater item
96
98
  * @returns the repeater item
97
99
  */
98
- function extractRepeaters(item: DetailItemRepeat) {
100
+ function extractRepeaters(item: DetailItemRepeat, translator: Translator) {
99
101
  const repeaters: Record<string, string>[] = []
100
102
 
101
103
  item.subItems.forEach((inputRepeaterItem) => {
@@ -105,9 +107,8 @@ function extractRepeaters(item: DetailItemRepeat) {
105
107
  outputRepeaterItem[repeaterComponent.name] = getAnswer(
106
108
  repeaterComponent.field,
107
109
  repeaterComponent.state,
108
- {
109
- format: 'data'
110
- }
110
+ translator,
111
+ { format: 'data' }
111
112
  )
112
113
  })
113
114
 
@@ -14,6 +14,7 @@ import {
14
14
  getError,
15
15
  getExponentialBackoffDelay
16
16
  } from '../helpers.js'
17
+ import { type Translator } from '../i18n/types.js'
17
18
  import { type FormModel } from '../models/index.js'
18
19
  import { QuestionPageController } from './QuestionPageController.js'
19
20
  import { getProxyUrlForLocalDevelopment } from './helpers/index.js'
@@ -187,10 +188,12 @@ export class FileUploadPageController extends QuestionPageController {
187
188
 
188
189
  const { filename } = fileToRemove.status.form.file
189
190
 
191
+ const { t } = this.getTranslator(request)
192
+
190
193
  return h.view(this.fileDeleteViewName, {
191
194
  ...viewModel,
192
195
  context,
193
- backLink: this.getBackLink(request, context),
196
+ backLink: this.getBackLink(request, context, t),
194
197
  pageTitle: `Are you sure you want to remove this file?`,
195
198
  itemTitle: filename,
196
199
  confirmation: { text: 'You cannot recover removed files.' },
@@ -258,14 +261,15 @@ export class FileUploadPageController extends QuestionPageController {
258
261
 
259
262
  getViewModel(
260
263
  request: FormContextRequest,
261
- context: FormContext
264
+ context: FormContext,
265
+ translator: Translator
262
266
  ): FeaturedFormPageViewModel {
263
267
  const { fileUpload } = this
264
268
  const { state } = context
265
269
 
266
270
  const upload = this.getUploadFromState(state)
267
271
 
268
- const viewModel = super.getViewModel(request, context)
272
+ const viewModel = super.getViewModel(request, context, translator)
269
273
  const { components } = viewModel
270
274
 
271
275
  // Featured form component
@@ -15,9 +15,11 @@ import {
15
15
  getStartPath,
16
16
  normalisePath
17
17
  } from '../helpers.js'
18
+ import { type Translator } from '../i18n/types.js'
18
19
  import { type FormModel } from '../models/index.js'
19
20
  import { type ExecutableCondition } from '../models/types.js'
20
21
  import {
22
+ type AnyFormRequest,
21
23
  type FormContext,
22
24
  type PageViewModelBase
23
25
  } from '../types.js'
@@ -28,6 +30,7 @@ import {
28
30
  type FormRequestRefs,
29
31
  type FormResponseToolkit
30
32
  } from '../../../routes/types.js'
33
+ import { resolveLanguage } from '../../../utils/utils.js'
31
34
 
32
35
  export class PageController {
33
36
  /**
@@ -161,6 +164,10 @@ export class PageController {
161
164
  return ControllerPath.Status.valueOf()
162
165
  }
163
166
 
167
+ protected getTranslator(request: AnyFormRequest): Translator {
168
+ return this.model.createTranslator(resolveLanguage(request))
169
+ }
170
+
164
171
  makeGetRouteHandler(): (
165
172
  request: FormRequest,
166
173
  context: FormContext,
@@ -168,7 +175,11 @@ export class PageController {
168
175
  ) => ReturnType<Lifecycle.Method<FormRequestRefs>> {
169
176
  return (request, context, h) => {
170
177
  const { viewModel, viewName } = this
171
- return h.view(viewName, viewModel)
178
+ const { t } = this.getTranslator(request)
179
+ return h.view(viewName, {
180
+ ...viewModel,
181
+ t
182
+ })
172
183
  }
173
184
  }
174
185
 
@@ -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