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

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 (278) hide show
  1. package/.public/javascripts/application.min.js +1 -1
  2. package/.public/javascripts/application.min.js.map +1 -1
  3. package/.public/javascripts/shared.min.js +1 -1
  4. package/.public/javascripts/shared.min.js.map +1 -1
  5. package/.public/stylesheets/application.min.css.map +1 -1
  6. package/.server/client/javascripts/file-upload.js +5 -3
  7. package/.server/client/javascripts/file-upload.js.map +1 -1
  8. package/.server/client/javascripts/geospatial-map.js +31 -26
  9. package/.server/client/javascripts/geospatial-map.js.map +1 -1
  10. package/.server/client/javascripts/location-map.js +9 -1
  11. package/.server/client/javascripts/location-map.js.map +1 -1
  12. package/.server/client/javascripts/maps.d.ts +5 -0
  13. package/.server/client/javascripts/maps.js +6 -0
  14. package/.server/client/javascripts/maps.js.map +1 -0
  15. package/.server/client/javascripts/shared.d.ts +1 -3
  16. package/.server/client/javascripts/shared.js +1 -3
  17. package/.server/client/javascripts/shared.js.map +1 -1
  18. package/.server/client/javascripts/sssi-dataset.d.ts +18 -20
  19. package/.server/client/javascripts/sssi-dataset.js +37 -39
  20. package/.server/client/javascripts/sssi-dataset.js.map +1 -1
  21. package/.server/client/stylesheets/maps.scss +4 -0
  22. package/.server/client/stylesheets/shared.scss +1 -5
  23. package/.server/server/constants.d.ts +2 -0
  24. package/.server/server/constants.js +2 -0
  25. package/.server/server/constants.js.map +1 -1
  26. package/.server/server/plugins/engine/components/AutocompleteField.d.ts +9 -3
  27. package/.server/server/plugins/engine/components/AutocompleteField.js +12 -0
  28. package/.server/server/plugins/engine/components/AutocompleteField.js.map +1 -1
  29. package/.server/server/plugins/engine/components/CheckboxesField.d.ts +4 -1
  30. package/.server/server/plugins/engine/components/CheckboxesField.js +13 -0
  31. package/.server/server/plugins/engine/components/CheckboxesField.js.map +1 -1
  32. package/.server/server/plugins/engine/components/ComponentBase.d.ts +1 -0
  33. package/.server/server/plugins/engine/components/ComponentBase.js +2 -0
  34. package/.server/server/plugins/engine/components/ComponentBase.js.map +1 -1
  35. package/.server/server/plugins/engine/components/ComponentCollection.js +11 -6
  36. package/.server/server/plugins/engine/components/ComponentCollection.js.map +1 -1
  37. package/.server/server/plugins/engine/components/DatePartsField.d.ts +6 -3
  38. package/.server/server/plugins/engine/components/DatePartsField.js +12 -7
  39. package/.server/server/plugins/engine/components/DatePartsField.js.map +1 -1
  40. package/.server/server/plugins/engine/components/DeclarationField.d.ts +5 -2
  41. package/.server/server/plugins/engine/components/DeclarationField.js +6 -4
  42. package/.server/server/plugins/engine/components/DeclarationField.js.map +1 -1
  43. package/.server/server/plugins/engine/components/Details.d.ts +1 -0
  44. package/.server/server/plugins/engine/components/EastingNorthingField.d.ts +26 -2
  45. package/.server/server/plugins/engine/components/EastingNorthingField.js +93 -54
  46. package/.server/server/plugins/engine/components/EastingNorthingField.js.map +1 -1
  47. package/.server/server/plugins/engine/components/EmailAddressField.d.ts +4 -1
  48. package/.server/server/plugins/engine/components/EmailAddressField.js +2 -1
  49. package/.server/server/plugins/engine/components/EmailAddressField.js.map +1 -1
  50. package/.server/server/plugins/engine/components/FileUploadField.d.ts +12 -0
  51. package/.server/server/plugins/engine/components/FileUploadField.js +20 -2
  52. package/.server/server/plugins/engine/components/FileUploadField.js.map +1 -1
  53. package/.server/server/plugins/engine/components/FormComponent.d.ts +5 -1
  54. package/.server/server/plugins/engine/components/FormComponent.js +5 -2
  55. package/.server/server/plugins/engine/components/FormComponent.js.map +1 -1
  56. package/.server/server/plugins/engine/components/GeospatialField.d.ts +1 -0
  57. package/.server/server/plugins/engine/components/GeospatialField.js +1 -1
  58. package/.server/server/plugins/engine/components/GeospatialField.js.map +1 -1
  59. package/.server/server/plugins/engine/components/Html.d.ts +1 -0
  60. package/.server/server/plugins/engine/components/InsetText.d.ts +1 -0
  61. package/.server/server/plugins/engine/components/LatLongField.d.ts +26 -2
  62. package/.server/server/plugins/engine/components/LatLongField.js +85 -48
  63. package/.server/server/plugins/engine/components/LatLongField.js.map +1 -1
  64. package/.server/server/plugins/engine/components/List.d.ts +1 -0
  65. package/.server/server/plugins/engine/components/ListFormComponent.d.ts +1 -0
  66. package/.server/server/plugins/engine/components/LocationFieldBase.d.ts +8 -2
  67. package/.server/server/plugins/engine/components/LocationFieldBase.js +18 -5
  68. package/.server/server/plugins/engine/components/LocationFieldBase.js.map +1 -1
  69. package/.server/server/plugins/engine/components/LocationFieldHelpers.d.ts +5 -2
  70. package/.server/server/plugins/engine/components/LocationFieldHelpers.js +10 -11
  71. package/.server/server/plugins/engine/components/LocationFieldHelpers.js.map +1 -1
  72. package/.server/server/plugins/engine/components/Markdown.d.ts +1 -0
  73. package/.server/server/plugins/engine/components/Markdown.js +1 -1
  74. package/.server/server/plugins/engine/components/Markdown.js.map +1 -1
  75. package/.server/server/plugins/engine/components/MonthYearField.d.ts +5 -2
  76. package/.server/server/plugins/engine/components/MonthYearField.js +13 -9
  77. package/.server/server/plugins/engine/components/MonthYearField.js.map +1 -1
  78. package/.server/server/plugins/engine/components/MultilineTextField.d.ts +1 -0
  79. package/.server/server/plugins/engine/components/NationalGridFieldNumberField.d.ts +2 -1
  80. package/.server/server/plugins/engine/components/NationalGridFieldNumberField.js +4 -3
  81. package/.server/server/plugins/engine/components/NationalGridFieldNumberField.js.map +1 -1
  82. package/.server/server/plugins/engine/components/NotificationBanner.d.ts +1 -0
  83. package/.server/server/plugins/engine/components/NumberField.d.ts +5 -0
  84. package/.server/server/plugins/engine/components/NumberField.js +16 -0
  85. package/.server/server/plugins/engine/components/NumberField.js.map +1 -1
  86. package/.server/server/plugins/engine/components/OsGridRefField.d.ts +2 -1
  87. package/.server/server/plugins/engine/components/OsGridRefField.js +4 -3
  88. package/.server/server/plugins/engine/components/OsGridRefField.js.map +1 -1
  89. package/.server/server/plugins/engine/components/PaymentField.d.ts +3 -0
  90. package/.server/server/plugins/engine/components/PaymentField.js +17 -6
  91. package/.server/server/plugins/engine/components/PaymentField.js.map +1 -1
  92. package/.server/server/plugins/engine/components/SelectField.d.ts +1 -0
  93. package/.server/server/plugins/engine/components/SelectionControlField.d.ts +1 -0
  94. package/.server/server/plugins/engine/components/TelephoneNumberField.d.ts +1 -0
  95. package/.server/server/plugins/engine/components/UkAddressField.d.ts +1 -0
  96. package/.server/server/plugins/engine/components/UkAddressField.js +23 -8
  97. package/.server/server/plugins/engine/components/UkAddressField.js.map +1 -1
  98. package/.server/server/plugins/engine/components/YesNoField.d.ts +5 -2
  99. package/.server/server/plugins/engine/components/YesNoField.js +17 -8
  100. package/.server/server/plugins/engine/components/YesNoField.js.map +1 -1
  101. package/.server/server/plugins/engine/components/helpers/components.js +1 -2
  102. package/.server/server/plugins/engine/components/helpers/components.js.map +1 -1
  103. package/.server/server/plugins/engine/components/helpers/index.d.ts +7 -0
  104. package/.server/server/plugins/engine/components/helpers/index.js +13 -1
  105. package/.server/server/plugins/engine/components/helpers/index.js.map +1 -1
  106. package/.server/server/plugins/engine/components/types.d.ts +1 -0
  107. package/.server/server/plugins/engine/components/types.js.map +1 -1
  108. package/.server/server/plugins/engine/helpers.d.ts +22 -2
  109. package/.server/server/plugins/engine/helpers.js +44 -5
  110. package/.server/server/plugins/engine/helpers.js.map +1 -1
  111. package/.server/server/plugins/engine/i18n/buildValidationMessages.d.ts +3 -0
  112. package/.server/server/plugins/engine/i18n/buildValidationMessages.js +10 -7
  113. package/.server/server/plugins/engine/i18n/buildValidationMessages.js.map +1 -1
  114. package/.server/server/plugins/engine/i18n/createFormTranslator.d.ts +4 -4
  115. package/.server/server/plugins/engine/i18n/createFormTranslator.js +33 -4
  116. package/.server/server/plugins/engine/i18n/createFormTranslator.js.map +1 -1
  117. package/.server/server/plugins/engine/i18n/extractBaseTranslations.d.ts +1 -1
  118. package/.server/server/plugins/engine/i18n/extractBaseTranslations.js +9 -0
  119. package/.server/server/plugins/engine/i18n/extractBaseTranslations.js.map +1 -1
  120. package/.server/server/plugins/engine/i18n/form.d.ts +13 -0
  121. package/.server/server/plugins/engine/i18n/form.js +35 -0
  122. package/.server/server/plugins/engine/i18n/form.js.map +1 -0
  123. package/.server/server/plugins/engine/i18n/languages.d.ts +10 -0
  124. package/.server/server/plugins/engine/i18n/languages.js +19 -0
  125. package/.server/server/plugins/engine/i18n/languages.js.map +1 -0
  126. package/.server/server/plugins/engine/i18n/translations/cy.json +73 -6
  127. package/.server/server/plugins/engine/i18n/translations/en-GB.json +43 -4
  128. package/.server/server/plugins/engine/i18n/types.d.ts +2 -0
  129. package/.server/server/plugins/engine/i18n/types.js.map +1 -1
  130. package/.server/server/plugins/engine/index.d.ts +4 -0
  131. package/.server/server/plugins/engine/index.js +4 -0
  132. package/.server/server/plugins/engine/index.js.map +1 -1
  133. package/.server/server/plugins/engine/models/FormModel.d.ts +0 -4
  134. package/.server/server/plugins/engine/models/FormModel.js +9 -15
  135. package/.server/server/plugins/engine/models/FormModel.js.map +1 -1
  136. package/.server/server/plugins/engine/models/SummaryViewModel.js +9 -4
  137. package/.server/server/plugins/engine/models/SummaryViewModel.js.map +1 -1
  138. package/.server/server/plugins/engine/outputFormatters/adapter/v1.js +3 -5
  139. package/.server/server/plugins/engine/outputFormatters/adapter/v1.js.map +1 -1
  140. package/.server/server/plugins/engine/outputFormatters/human/v1.js +2 -1
  141. package/.server/server/plugins/engine/outputFormatters/human/v1.js.map +1 -1
  142. package/.server/server/plugins/engine/outputFormatters/machine/v2.d.ts +2 -0
  143. package/.server/server/plugins/engine/outputFormatters/machine/v2.js +2 -0
  144. package/.server/server/plugins/engine/outputFormatters/machine/v2.js.map +1 -1
  145. package/.server/server/plugins/engine/pageControllers/FileUploadPageController.d.ts +1 -1
  146. package/.server/server/plugins/engine/pageControllers/FileUploadPageController.js +22 -9
  147. package/.server/server/plugins/engine/pageControllers/FileUploadPageController.js.map +1 -1
  148. package/.server/server/plugins/engine/pageControllers/QuestionPageController.d.ts +1 -1
  149. package/.server/server/plugins/engine/pageControllers/QuestionPageController.js +7 -3
  150. package/.server/server/plugins/engine/pageControllers/QuestionPageController.js.map +1 -1
  151. package/.server/server/plugins/engine/pageControllers/RepeatPageController.js +3 -4
  152. package/.server/server/plugins/engine/pageControllers/RepeatPageController.js.map +1 -1
  153. package/.server/server/plugins/engine/pageControllers/SummaryPageController.js +10 -4
  154. package/.server/server/plugins/engine/pageControllers/SummaryPageController.js.map +1 -1
  155. package/.server/server/plugins/engine/pageControllers/helpers/submission.d.ts +1 -1
  156. package/.server/server/plugins/engine/pageControllers/helpers/submission.js +3 -3
  157. package/.server/server/plugins/engine/pageControllers/helpers/submission.js.map +1 -1
  158. package/.server/server/plugins/engine/pageControllers/validationOptions.js +23 -2
  159. package/.server/server/plugins/engine/pageControllers/validationOptions.js.map +1 -1
  160. package/.server/server/plugins/engine/types/schema.js +1 -0
  161. package/.server/server/plugins/engine/types/schema.js.map +1 -1
  162. package/.server/server/plugins/engine/types.d.ts +1 -0
  163. package/.server/server/plugins/engine/types.js.map +1 -1
  164. package/.server/server/plugins/engine/views/components/fileuploadfield.html +1 -1
  165. package/.server/server/plugins/engine/views/components/multilinetextfield.html +12 -1
  166. package/.server/server/plugins/engine/views/components/paymentfield.html +1 -1
  167. package/.server/server/plugins/engine/views/components/ukaddressfield.html +1 -1
  168. package/.server/server/plugins/engine/views/partials/preview-banner.html +3 -1
  169. package/.server/server/plugins/nunjucks/filters/applyUrlParam.d.ts +9 -0
  170. package/.server/server/plugins/nunjucks/filters/applyUrlParam.js +17 -0
  171. package/.server/server/plugins/nunjucks/filters/applyUrlParam.js.map +1 -0
  172. package/.server/server/plugins/nunjucks/filters/applyUrlParam.test.js +17 -0
  173. package/.server/server/plugins/nunjucks/filters/applyUrlParam.test.js.map +1 -0
  174. package/.server/server/plugins/nunjucks/filters/field.d.ts +1 -1
  175. package/.server/server/plugins/nunjucks/filters/index.d.ts +1 -0
  176. package/.server/server/plugins/nunjucks/filters/index.js +1 -0
  177. package/.server/server/plugins/nunjucks/filters/index.js.map +1 -1
  178. package/.server/server/plugins/payment/helper.d.ts +11 -1
  179. package/.server/server/plugins/payment/helper.js +18 -2
  180. package/.server/server/plugins/payment/helper.js.map +1 -1
  181. package/.server/server/plugins/payment/helper.test.js +2 -1
  182. package/.server/server/plugins/payment/helper.test.js.map +1 -1
  183. package/.server/server/plugins/payment/service.d.ts +2 -1
  184. package/.server/server/plugins/payment/service.js +5 -2
  185. package/.server/server/plugins/payment/service.js.map +1 -1
  186. package/.server/server/plugins/payment/service.test.js +7 -3
  187. package/.server/server/plugins/payment/service.test.js.map +1 -1
  188. package/.server/server/plugins/payment/types.d.ts +4 -0
  189. package/.server/server/plugins/payment/types.js +1 -0
  190. package/.server/server/plugins/payment/types.js.map +1 -1
  191. package/.server/server/plugins/postcode-lookup/models/index.d.ts +249 -3
  192. package/.server/server/plugins/postcode-lookup/models/index.js +87 -33
  193. package/.server/server/plugins/postcode-lookup/models/index.js.map +1 -1
  194. package/.server/server/plugins/postcode-lookup/routes/index.d.ts +15 -1
  195. package/.server/server/plugins/postcode-lookup/routes/index.js +47 -15
  196. package/.server/server/plugins/postcode-lookup/routes/index.js.map +1 -1
  197. package/.server/server/plugins/postcode-lookup/routes/index.test.js +84 -0
  198. package/.server/server/plugins/postcode-lookup/routes/index.test.js.map +1 -0
  199. package/.server/server/plugins/postcode-lookup/types.d.ts +12 -0
  200. package/.server/server/plugins/postcode-lookup/types.js +6 -1
  201. package/.server/server/plugins/postcode-lookup/types.js.map +1 -1
  202. package/.server/server/plugins/postcode-lookup/views/postcode-lookup-details.html +3 -3
  203. package/.server/server/utils/type-utils.d.ts +1 -2
  204. package/.server/server/utils/type-utils.js +0 -3
  205. package/.server/server/utils/type-utils.js.map +1 -1
  206. package/package.json +8 -2
  207. package/src/client/javascripts/file-upload.js +10 -3
  208. package/src/client/javascripts/geospatial-map.js +32 -30
  209. package/src/client/javascripts/location-map.js +7 -1
  210. package/src/client/javascripts/maps.js +5 -0
  211. package/src/client/javascripts/shared.js +1 -3
  212. package/src/client/javascripts/sssi-dataset.js +39 -41
  213. package/src/client/stylesheets/maps.scss +4 -0
  214. package/src/client/stylesheets/shared.scss +1 -5
  215. package/src/server/constants.js +2 -0
  216. package/src/server/plugins/engine/components/AutocompleteField.ts +13 -0
  217. package/src/server/plugins/engine/components/CheckboxesField.ts +13 -1
  218. package/src/server/plugins/engine/components/ComponentBase.ts +2 -0
  219. package/src/server/plugins/engine/components/ComponentCollection.ts +16 -11
  220. package/src/server/plugins/engine/components/DatePartsField.ts +20 -9
  221. package/src/server/plugins/engine/components/DeclarationField.ts +7 -6
  222. package/src/server/plugins/engine/components/EastingNorthingField.ts +154 -89
  223. package/src/server/plugins/engine/components/EmailAddressField.ts +2 -1
  224. package/src/server/plugins/engine/components/FileUploadField.ts +21 -2
  225. package/src/server/plugins/engine/components/FormComponent.ts +6 -5
  226. package/src/server/plugins/engine/components/GeospatialField.ts +6 -1
  227. package/src/server/plugins/engine/components/LatLongField.ts +128 -58
  228. package/src/server/plugins/engine/components/LocationFieldBase.ts +23 -6
  229. package/src/server/plugins/engine/components/LocationFieldHelpers.ts +14 -11
  230. package/src/server/plugins/engine/components/Markdown.ts +2 -3
  231. package/src/server/plugins/engine/components/MonthYearField.ts +20 -15
  232. package/src/server/plugins/engine/components/NationalGridFieldNumberField.ts +9 -3
  233. package/src/server/plugins/engine/components/NumberField.ts +21 -1
  234. package/src/server/plugins/engine/components/OsGridRefField.ts +9 -3
  235. package/src/server/plugins/engine/components/PaymentField.ts +15 -5
  236. package/src/server/plugins/engine/components/UkAddressField.ts +30 -7
  237. package/src/server/plugins/engine/components/YesNoField.ts +17 -9
  238. package/src/server/plugins/engine/components/helpers/components.ts +1 -2
  239. package/src/server/plugins/engine/components/helpers/index.ts +19 -0
  240. package/src/server/plugins/engine/components/types.ts +1 -0
  241. package/src/server/plugins/engine/helpers.ts +52 -5
  242. package/src/server/plugins/engine/i18n/buildValidationMessages.ts +10 -7
  243. package/src/server/plugins/engine/i18n/createFormTranslator.ts +62 -11
  244. package/src/server/plugins/engine/i18n/extractBaseTranslations.ts +7 -1
  245. package/src/server/plugins/engine/i18n/form.ts +54 -0
  246. package/src/server/plugins/engine/i18n/languages.ts +19 -0
  247. package/src/server/plugins/engine/i18n/translations/cy.json +73 -6
  248. package/src/server/plugins/engine/i18n/translations/en-GB.json +43 -4
  249. package/src/server/plugins/engine/i18n/types.ts +2 -0
  250. package/src/server/plugins/engine/index.ts +7 -0
  251. package/src/server/plugins/engine/models/FormModel.ts +9 -15
  252. package/src/server/plugins/engine/models/SummaryViewModel.ts +6 -5
  253. package/src/server/plugins/engine/outputFormatters/adapter/v1.ts +3 -6
  254. package/src/server/plugins/engine/outputFormatters/human/v1.ts +2 -1
  255. package/src/server/plugins/engine/outputFormatters/machine/v2.ts +3 -0
  256. package/src/server/plugins/engine/pageControllers/FileUploadPageController.ts +18 -8
  257. package/src/server/plugins/engine/pageControllers/QuestionPageController.ts +10 -5
  258. package/src/server/plugins/engine/pageControllers/RepeatPageController.ts +2 -2
  259. package/src/server/plugins/engine/pageControllers/SummaryPageController.ts +15 -4
  260. package/src/server/plugins/engine/pageControllers/helpers/submission.ts +6 -3
  261. package/src/server/plugins/engine/pageControllers/validationOptions.ts +27 -2
  262. package/src/server/plugins/engine/types/schema.ts +1 -0
  263. package/src/server/plugins/engine/types.ts +1 -0
  264. package/src/server/plugins/engine/views/components/fileuploadfield.html +1 -1
  265. package/src/server/plugins/engine/views/components/multilinetextfield.html +12 -1
  266. package/src/server/plugins/engine/views/components/paymentfield.html +1 -1
  267. package/src/server/plugins/engine/views/components/ukaddressfield.html +1 -1
  268. package/src/server/plugins/engine/views/partials/preview-banner.html +3 -1
  269. package/src/server/plugins/nunjucks/filters/applyUrlParam.js +17 -0
  270. package/src/server/plugins/nunjucks/filters/index.js +1 -0
  271. package/src/server/plugins/payment/helper.js +22 -2
  272. package/src/server/plugins/payment/service.js +6 -2
  273. package/src/server/plugins/payment/types.js +1 -0
  274. package/src/server/plugins/postcode-lookup/models/index.js +75 -43
  275. package/src/server/plugins/postcode-lookup/routes/index.js +73 -16
  276. package/src/server/plugins/postcode-lookup/types.js +6 -1
  277. package/src/server/plugins/postcode-lookup/views/postcode-lookup-details.html +3 -3
  278. package/src/server/utils/type-utils.ts +1 -11
@@ -15,7 +15,10 @@ import {
15
15
  getLocationFieldViewModel
16
16
  } from './LocationFieldHelpers.js'
17
17
  import { NumberField } from './NumberField.js'
18
- import { createLowerFirstExpression } from './helpers/index.js'
18
+ import {
19
+ createLowerFirstExpression,
20
+ getTranslatedLabel
21
+ } from './helpers/index.js'
19
22
  import {
20
23
  type EastingNorthingState,
21
24
  type RenderContext
@@ -31,7 +34,6 @@ import {
31
34
  type FormSubmissionError,
32
35
  type FormSubmissionState
33
36
  } from '../types.js'
34
- import { convertToLanguageMessages } from '../../../utils/type-utils.js'
35
37
 
36
38
  // British National Grid coordinate limits
37
39
  const DEFAULT_EASTING_MIN = 0
@@ -55,89 +57,18 @@ export class EastingNorthingField extends FormComponent {
55
57
 
56
58
  const isRequired = options.required !== false
57
59
 
58
- const eastingMin = schema?.easting?.min ?? DEFAULT_EASTING_MIN
59
- const eastingMax = schema?.easting?.max ?? DEFAULT_EASTING_MAX
60
- const northingMin = schema?.northing?.min ?? DEFAULT_NORTHING_MIN
61
- const northingMax = schema?.northing?.max ?? DEFAULT_NORTHING_MAX
62
-
63
- const fieldLabel = lowerFirst(this.label)
60
+ const { eastingMin, eastingMax, northingMin, northingMax } =
61
+ EastingNorthingField.getMinMax(schema)
64
62
 
65
- const eastingDigitsMessage = tPlugin(
66
- 'components.eastingNorthingField.eastingDigits',
67
- 'en-GB',
68
- { fieldLabel }
69
- )
70
- const northingDigitsMessage = tPlugin(
71
- 'components.eastingNorthingField.northingDigits',
72
- 'en-GB',
73
- { fieldLabel }
74
- )
75
-
76
- const customValidationMessages: LanguageMessages =
77
- convertToLanguageMessages({
78
- 'any.required': tPlugin(
79
- 'components.eastingNorthingField.eastingRequired',
80
- 'en-GB'
81
- ),
82
- 'number.base': tPlugin(
83
- 'components.eastingNorthingField.eastingRequired',
84
- 'en-GB'
85
- ),
86
- 'number.min': tPlugin(
87
- 'components.eastingNorthingField.eastingRange',
88
- 'en-GB',
89
- {
90
- fieldLabel,
91
- min: eastingMin,
92
- max: eastingMax
93
- }
94
- ),
95
- 'number.max': tPlugin(
96
- 'components.eastingNorthingField.eastingRange',
97
- 'en-GB',
98
- {
99
- fieldLabel,
100
- min: eastingMin,
101
- max: eastingMax
102
- }
103
- ),
104
- 'number.precision': eastingDigitsMessage,
105
- 'number.integer': eastingDigitsMessage,
106
- 'number.unsafe': eastingDigitsMessage
107
- })
108
-
109
- const northingValidationMessages: LanguageMessages =
110
- convertToLanguageMessages({
111
- 'any.required': tPlugin(
112
- 'components.eastingNorthingField.northingRequired',
113
- 'en-GB'
114
- ),
115
- 'number.base': tPlugin(
116
- 'components.eastingNorthingField.northingRequired',
117
- 'en-GB'
118
- ),
119
- 'number.min': tPlugin(
120
- 'components.eastingNorthingField.northingRange',
121
- 'en-GB',
122
- {
123
- fieldLabel,
124
- min: northingMin,
125
- max: northingMax
126
- }
127
- ),
128
- 'number.max': tPlugin(
129
- 'components.eastingNorthingField.northingRange',
130
- 'en-GB',
131
- {
132
- fieldLabel,
133
- min: northingMin,
134
- max: northingMax
135
- }
136
- ),
137
- 'number.precision': northingDigitsMessage,
138
- 'number.integer': northingDigitsMessage,
139
- 'number.unsafe': northingDigitsMessage
140
- })
63
+ const { eastingValidationMessages, northingValidationMessages } =
64
+ EastingNorthingField.buildErrorMessages(
65
+ this.label,
66
+ eastingMin,
67
+ eastingMax,
68
+ northingMin,
69
+ northingMax,
70
+ 'en-GB'
71
+ )
141
72
 
142
73
  this.collection = new ComponentCollection(
143
74
  [
@@ -154,7 +85,7 @@ export class EastingNorthingField extends FormComponent {
154
85
  required: isRequired,
155
86
  optionalText: true,
156
87
  classes: 'govuk-input--width-10',
157
- customValidationMessages
88
+ customValidationMessages: eastingValidationMessages
158
89
  }
159
90
  },
160
91
  {
@@ -192,14 +123,15 @@ export class EastingNorthingField extends FormComponent {
192
123
 
193
124
  getDisplayStringFromFormValue(
194
125
  value: EastingNorthingState | undefined,
195
- _translator: Translator
126
+ translator: Translator
196
127
  ): string {
197
128
  if (!value) {
198
129
  return ''
199
130
  }
200
131
 
201
- // CYA page format: <<eastingvalue, northingvalue>>
202
- return `${value.easting}, ${value.northing}`
132
+ const { t } = translator
133
+
134
+ return `${t('components.eastingNorthingField.easting')}: ${value.easting}\n${t('components.eastingNorthingField.northing')}: ${value.northing}`
203
135
  }
204
136
 
205
137
  getDisplayStringFromState(
@@ -218,7 +150,7 @@ export class EastingNorthingField extends FormComponent {
218
150
  return null
219
151
  }
220
152
 
221
- return `Easting: ${value.easting}\nNorthing: ${value.northing}`
153
+ return `${value.easting}, ${value.northing}`
222
154
  }
223
155
 
224
156
  getContextValueFromState(state: FormSubmissionState) {
@@ -244,6 +176,26 @@ export class EastingNorthingField extends FormComponent {
244
176
  return EastingNorthingField.isEastingNorthing(value)
245
177
  }
246
178
 
179
+ getValidationMessagesOverride(translator: Translator) {
180
+ const def = this.def as EastingNorthingFieldComponent
181
+ const translatedLabel = getTranslatedLabel(def, translator)
182
+ const { eastingMin, eastingMax, northingMin, northingMax } =
183
+ EastingNorthingField.getMinMax(def.schema)
184
+ const { eastingValidationMessages, northingValidationMessages } =
185
+ EastingNorthingField.buildErrorMessages(
186
+ translatedLabel,
187
+ eastingMin,
188
+ eastingMax,
189
+ northingMin,
190
+ northingMax,
191
+ translator.language
192
+ )
193
+ return {
194
+ [`${this.name}__easting`]: eastingValidationMessages,
195
+ [`${this.name}__northing`]: northingValidationMessages
196
+ }
197
+ }
198
+
247
199
  /**
248
200
  * For error preview page that shows all possible errors on a component
249
201
  */
@@ -309,4 +261,117 @@ export class EastingNorthingField extends FormComponent {
309
261
  NumberField.isNumber(value.northing)
310
262
  )
311
263
  }
264
+
265
+ static buildErrorMessages(
266
+ label: string,
267
+ eastingMin: number,
268
+ eastingMax: number,
269
+ northingMin: number,
270
+ northingMax: number,
271
+ language: string
272
+ ) {
273
+ const fieldLabel = lowerFirst(label)
274
+
275
+ const eastingDigitsMessage = tPlugin(
276
+ 'components.eastingNorthingField.eastingDigits',
277
+ language,
278
+ { fieldLabel }
279
+ )
280
+ const northingDigitsMessage = tPlugin(
281
+ 'components.eastingNorthingField.northingDigits',
282
+ language,
283
+ { fieldLabel }
284
+ )
285
+
286
+ const eastingValidationMessages: LanguageMessages = {
287
+ 'any.required': tPlugin(
288
+ 'components.eastingNorthingField.eastingRequired',
289
+ language
290
+ ),
291
+ 'number.base': tPlugin(
292
+ 'components.eastingNorthingField.eastingRequired',
293
+ language
294
+ ),
295
+ 'number.min': tPlugin(
296
+ 'components.eastingNorthingField.eastingRange',
297
+ language,
298
+ {
299
+ fieldLabel,
300
+ min: eastingMin,
301
+ max: eastingMax
302
+ }
303
+ ),
304
+ 'number.max': tPlugin(
305
+ 'components.eastingNorthingField.eastingRange',
306
+ language,
307
+ {
308
+ fieldLabel,
309
+ min: eastingMin,
310
+ max: eastingMax
311
+ }
312
+ ),
313
+ 'number.precision': eastingDigitsMessage,
314
+ 'number.integer': eastingDigitsMessage,
315
+ 'number.unsafe': eastingDigitsMessage
316
+ }
317
+
318
+ const northingValidationMessages: LanguageMessages = {
319
+ 'any.required': tPlugin(
320
+ 'components.eastingNorthingField.northingRequired',
321
+ language
322
+ ),
323
+ 'number.base': tPlugin(
324
+ 'components.eastingNorthingField.northingRequired',
325
+ language
326
+ ),
327
+ 'number.min': tPlugin(
328
+ 'components.eastingNorthingField.northingRange',
329
+ language,
330
+ {
331
+ fieldLabel,
332
+ min: northingMin,
333
+ max: northingMax
334
+ }
335
+ ),
336
+ 'number.max': tPlugin(
337
+ 'components.eastingNorthingField.northingRange',
338
+ language,
339
+ {
340
+ fieldLabel,
341
+ min: northingMin,
342
+ max: northingMax
343
+ }
344
+ ),
345
+ 'number.precision': northingDigitsMessage,
346
+ 'number.integer': northingDigitsMessage,
347
+ 'number.unsafe': northingDigitsMessage
348
+ }
349
+ return {
350
+ eastingValidationMessages,
351
+ northingValidationMessages
352
+ }
353
+ }
354
+
355
+ // Read schema values from def.schema with fallback defaults
356
+ static getMinMax(
357
+ schema:
358
+ | {
359
+ easting?: {
360
+ min?: number
361
+ max?: number
362
+ }
363
+ northing?: {
364
+ min?: number
365
+ max?: number
366
+ }
367
+ }
368
+ | undefined
369
+ ) {
370
+ return {
371
+ eastingMin: schema?.easting?.min ?? DEFAULT_EASTING_MIN,
372
+ eastingMax: schema?.easting?.max ?? DEFAULT_EASTING_MAX,
373
+ northingMin: schema?.northing?.min ?? DEFAULT_NORTHING_MIN,
374
+ northingMax: schema?.northing?.max ?? DEFAULT_NORTHING_MAX
375
+ }
376
+ }
312
377
  }
@@ -40,7 +40,8 @@ export class EmailAddressField extends FormComponent {
40
40
  formSchema = formSchema.messages({
41
41
  'any.required': message,
42
42
  'string.empty': message,
43
- 'string.email': message
43
+ 'string.email': message,
44
+ 'string.unicode': message
44
45
  })
45
46
  } else if (options.customValidationMessages) {
46
47
  formSchema = formSchema.messages(options.customValidationMessages)
@@ -5,11 +5,13 @@ import {
5
5
  import Boom from '@hapi/boom'
6
6
  import joi, { type ArraySchema } from 'joi'
7
7
 
8
+ import { EN_GB } from '../../../constants.js'
8
9
  import {
9
10
  FormComponent,
10
11
  isUploadState
11
12
  } from './FormComponent.js'
12
13
  import { type RenderContext } from './types.js'
14
+ import { t as tPlugin } from '../i18n/index.js'
13
15
  import { type Translator } from '../i18n/types.js'
14
16
  import { InvalidComponentStateError } from '../pageControllers/errors.js'
15
17
  import { messageTemplate } from '../pageControllers/validationOptions.js'
@@ -142,6 +144,8 @@ export class FileUploadField extends FormComponent {
142
144
  formSchema = formSchema.length(schema.length)
143
145
  }
144
146
 
147
+ formSchema = formSchema.messages(FileUploadField.buildErrorMessages(EN_GB))
148
+
145
149
  this.formSchema = formSchema.items(formItemSchema)
146
150
  this.stateSchema = formSchema
147
151
  .items(formItemSchema)
@@ -169,7 +173,7 @@ export class FileUploadField extends FormComponent {
169
173
  return ''
170
174
  }
171
175
 
172
- return translator.t('components.fileUploadField.filesCount', {
176
+ return translator.t('pages.summary.fileUpload', {
173
177
  count: files.length
174
178
  })
175
179
  }
@@ -244,7 +248,7 @@ export class FileUploadField extends FormComponent {
244
248
 
245
249
  items.push({
246
250
  href,
247
- text: 'Remove',
251
+ text: t('pages.fileUpload.remove'),
248
252
  classes: 'govuk-link--no-visited-state',
249
253
  attributes: { id: `${id}__${index}` },
250
254
  visuallyHiddenText: file.filename
@@ -300,6 +304,13 @@ export class FileUploadField extends FormComponent {
300
304
  return isUploadState(value)
301
305
  }
302
306
 
307
+ getValidationMessagesOverride(translator: Translator) {
308
+ const { language } = translator
309
+ return {
310
+ [this.name]: FileUploadField.buildErrorMessages(language)
311
+ }
312
+ }
313
+
303
314
  /**
304
315
  * For error preview page that shows all possible errors on a component
305
316
  */
@@ -403,4 +414,12 @@ export class FileUploadField extends FormComponent {
403
414
  ]
404
415
  }
405
416
  }
417
+
418
+ static buildErrorMessages(language: string) {
419
+ return {
420
+ 'array.min': tPlugin('validation.filesMin', language),
421
+ 'array.max': tPlugin('validation.filesMax', language),
422
+ 'array.length': tPlugin('validation.filesLength', language)
423
+ }
424
+ }
406
425
  }
@@ -1,5 +1,4 @@
1
1
  import {
2
- type ComponentDef,
3
2
  type FormComponentsDef,
4
3
  type FormMetadata,
5
4
  type Item
@@ -158,10 +157,13 @@ export class FormComponent extends ComponentBase {
158
157
  * Override in composite fields to return translated Joi message overrides for
159
158
  * their sub-fields, applied at validation time so schema-level English messages
160
159
  * are replaced with the correct language. Return null to skip message patching.
160
+ * The return object may contain message overrides at component-level, or sub-field-level.
161
+ * This would allow different error message overrides per field within a collection e.g.
162
+ * for EastingNothingField
161
163
  */
162
164
  getValidationMessagesOverride(
163
165
  _translator: Translator
164
- ): LanguageMessages | null {
166
+ ): Record<string, LanguageMessages> | null {
165
167
  return null
166
168
  }
167
169
 
@@ -178,15 +180,14 @@ export class FormComponent extends ComponentBase {
178
180
  const isRequired = !('required' in options) || options.required !== false
179
181
  const hideOptional = 'optionalText' in options && options.optionalText
180
182
 
181
- const resolvedTitle =
182
- tComponent(this as unknown as ComponentDef, 'title') || title
183
+ const resolvedTitle = tComponent(this.def, 'title') || title
183
184
  const optionalTag =
184
185
  !isRequired && !hideOptional ? ` ${t('common.optional')}` : ''
185
186
  const label = `${resolvedTitle}${optionalTag}`
186
187
 
187
188
  if (hint) {
188
189
  viewModel.hint = {
189
- text: tComponent(this as unknown as ComponentDef, 'hint') || hint
190
+ text: tComponent(this.def, 'hint') || hint
190
191
  }
191
192
  }
192
193
 
@@ -125,7 +125,12 @@ export class GeospatialField extends FormComponent {
125
125
  err.href = `#description_${err.path[1]}`
126
126
  err.text = translator.t(
127
127
  'components.geospatialField.validation.wrongCountry',
128
- { count: Number(err.path[1]) + 1, country: err.context.country }
128
+ {
129
+ count: Number(err.path[1]) + 1,
130
+ country: translator.t(
131
+ `common.${(err.context.country as string).toLowerCase()}`
132
+ )
133
+ }
129
134
  )
130
135
  }
131
136
  })
@@ -12,7 +12,10 @@ import {
12
12
  getLocationFieldViewModel
13
13
  } from './LocationFieldHelpers.js'
14
14
  import { NumberField } from './NumberField.js'
15
- import { createLowerFirstExpression } from './helpers/index.js'
15
+ import {
16
+ createLowerFirstExpression,
17
+ getTranslatedLabel
18
+ } from './helpers/index.js'
16
19
  import {
17
20
  type LatLongState,
18
21
  type RenderContext
@@ -28,7 +31,6 @@ import {
28
31
  type FormSubmissionError,
29
32
  type FormSubmissionState
30
33
  } from '../types.js'
31
- import { convertToLanguageMessages } from '../../../utils/type-utils.js'
32
34
 
33
35
  // Precision constants
34
36
  // UK latitude/longitude requires high precision for accurate location (within ~11mm)
@@ -50,59 +52,18 @@ export class LatLongField extends FormComponent {
50
52
 
51
53
  const isRequired = options.required !== false
52
54
 
53
- // Read schema values from def.schema with fallback defaults
54
- const latitudeMin = schema?.latitude?.min ?? 49.85
55
- const latitudeMax = schema?.latitude?.max ?? 60.859
56
- const longitudeMin = schema?.longitude?.min ?? -13.687
57
- const longitudeMax = schema?.longitude?.max ?? 1.767
58
-
59
- const fieldLabel = lowerFirst(this.label)
60
-
61
- const customValidationMessages: LanguageMessages =
62
- convertToLanguageMessages({
63
- 'number.precision': tPlugin(
64
- 'components.latLongField.precision',
65
- 'en-GB'
66
- ),
67
- 'number.unsafe': tPlugin('components.latLongField.notANumber', 'en-GB')
68
- })
69
-
70
- const latitudeRangeMessage = tPlugin(
71
- 'components.latLongField.latitudeRange',
72
- 'en-GB',
73
- { fieldLabel, min: latitudeMin, max: latitudeMax }
74
- )
75
- const longitudeRangeMessage = tPlugin(
76
- 'components.latLongField.longitudeRange',
77
- 'en-GB',
78
- { fieldLabel, min: longitudeMin, max: longitudeMax }
79
- )
80
-
81
- const latitudeMessages: LanguageMessages = convertToLanguageMessages({
82
- ...customValidationMessages,
83
- 'any.required': tPlugin(
84
- 'components.latLongField.latitudeRequired',
85
- 'en-GB'
86
- ),
87
- 'number.base': tPlugin('components.latLongField.latitudeBase', 'en-GB', {
88
- fieldLabel
89
- }),
90
- 'number.min': latitudeRangeMessage,
91
- 'number.max': latitudeRangeMessage
92
- })
55
+ const { latitudeMin, latitudeMax, longitudeMin, longitudeMax } =
56
+ LatLongField.getMinMax(schema)
93
57
 
94
- const longitudeMessages: LanguageMessages = convertToLanguageMessages({
95
- ...customValidationMessages,
96
- 'any.required': tPlugin(
97
- 'components.latLongField.longitudeRequired',
58
+ const { latitudeMessages, longitudeMessages } =
59
+ LatLongField.buildErrorMessages(
60
+ this.label,
61
+ latitudeMin,
62
+ latitudeMax,
63
+ longitudeMin,
64
+ longitudeMax,
98
65
  'en-GB'
99
- ),
100
- 'number.base': tPlugin('components.latLongField.longitudeBase', 'en-GB', {
101
- fieldLabel
102
- }),
103
- 'number.min': longitudeRangeMessage,
104
- 'number.max': longitudeRangeMessage
105
- })
66
+ )
106
67
 
107
68
  this.collection = new ComponentCollection(
108
69
  [
@@ -159,14 +120,16 @@ export class LatLongField extends FormComponent {
159
120
 
160
121
  getDisplayStringFromFormValue(
161
122
  value: LatLongState | undefined,
162
- _translator: Translator
123
+ translator: Translator
163
124
  ): string {
164
125
  if (!value) {
165
126
  return ''
166
127
  }
167
128
 
168
- // CYA page format: <<latvalue, langvalue>>
169
- return `${value.latitude}, ${value.longitude}`
129
+ const { t } = translator
130
+
131
+ // Output format: Latitude: <<entry>>\nLongitude: <<entry>>
132
+ return `${t('components.latLongField.latitude')}: ${value.latitude}\n${t('components.latLongField.longitude')}: ${value.longitude}`
170
133
  }
171
134
 
172
135
  getDisplayStringFromState(
@@ -183,8 +146,7 @@ export class LatLongField extends FormComponent {
183
146
  return null
184
147
  }
185
148
 
186
- // Output format: Latitude: <<entry>>\nLongitude: <<entry>>
187
- return `Latitude: ${value.latitude}\nLongitude: ${value.longitude}`
149
+ return `${value.latitude}, ${value.longitude}`
188
150
  }
189
151
 
190
152
  getContextValueFromState(state: FormSubmissionState) {
@@ -210,6 +172,26 @@ export class LatLongField extends FormComponent {
210
172
  return LatLongField.isLatLong(value)
211
173
  }
212
174
 
175
+ getValidationMessagesOverride(translator: Translator) {
176
+ const def = this.def as LatLongFieldComponent
177
+ const translatedLabel = getTranslatedLabel(def, translator)
178
+ const { latitudeMin, latitudeMax, longitudeMin, longitudeMax } =
179
+ LatLongField.getMinMax(def.schema)
180
+ const { latitudeMessages, longitudeMessages } =
181
+ LatLongField.buildErrorMessages(
182
+ translatedLabel,
183
+ latitudeMin,
184
+ latitudeMax,
185
+ longitudeMin,
186
+ longitudeMax,
187
+ translator.language
188
+ )
189
+ return {
190
+ [`${this.name}__latitude`]: latitudeMessages,
191
+ [`${this.name}__longitude`]: longitudeMessages
192
+ }
193
+ }
194
+
213
195
  /**
214
196
  * For error preview page that shows all possible errors on a component
215
197
  */
@@ -273,4 +255,92 @@ export class LatLongField extends FormComponent {
273
255
  NumberField.isNumber(value.longitude)
274
256
  )
275
257
  }
258
+
259
+ static buildErrorMessages(
260
+ label: string,
261
+ latitudeMin: number,
262
+ latitudeMax: number,
263
+ longitudeMin: number,
264
+ longitudeMax: number,
265
+ language: string
266
+ ) {
267
+ const fieldLabel = lowerFirst(label)
268
+
269
+ const customValidationMessages: LanguageMessages = {
270
+ 'number.precision': tPlugin(
271
+ 'components.latLongField.precision',
272
+ language
273
+ ),
274
+ 'number.unsafe': tPlugin('components.latLongField.notANumber', language)
275
+ }
276
+
277
+ const latitudeRangeMessage = tPlugin(
278
+ 'components.latLongField.latitudeRange',
279
+ language,
280
+ { fieldLabel, min: latitudeMin, max: latitudeMax }
281
+ )
282
+ const longitudeRangeMessage = tPlugin(
283
+ 'components.latLongField.longitudeRange',
284
+ language,
285
+ { fieldLabel, min: longitudeMin, max: longitudeMax }
286
+ )
287
+
288
+ const latitudeMessages: LanguageMessages = {
289
+ ...customValidationMessages,
290
+ 'any.required': tPlugin(
291
+ 'components.latLongField.latitudeRequired',
292
+ language
293
+ ),
294
+ 'number.base': tPlugin('components.latLongField.latitudeBase', language, {
295
+ fieldLabel
296
+ }),
297
+ 'number.min': latitudeRangeMessage,
298
+ 'number.max': latitudeRangeMessage
299
+ }
300
+
301
+ const longitudeMessages: LanguageMessages = {
302
+ ...customValidationMessages,
303
+ 'any.required': tPlugin(
304
+ 'components.latLongField.longitudeRequired',
305
+ language
306
+ ),
307
+ 'number.base': tPlugin(
308
+ 'components.latLongField.longitudeBase',
309
+ language,
310
+ {
311
+ fieldLabel
312
+ }
313
+ ),
314
+ 'number.min': longitudeRangeMessage,
315
+ 'number.max': longitudeRangeMessage
316
+ }
317
+
318
+ return {
319
+ latitudeMessages,
320
+ longitudeMessages
321
+ }
322
+ }
323
+
324
+ // Read schema values from def.schema with fallback defaults
325
+ static getMinMax(
326
+ schema:
327
+ | {
328
+ latitude?: {
329
+ min?: number
330
+ max?: number
331
+ }
332
+ longitude?: {
333
+ min?: number
334
+ max?: number
335
+ }
336
+ }
337
+ | undefined
338
+ ) {
339
+ return {
340
+ latitudeMin: schema?.latitude?.min ?? 49.85,
341
+ latitudeMax: schema?.latitude?.max ?? 60.859,
342
+ longitudeMin: schema?.longitude?.min ?? -13.687,
343
+ longitudeMax: schema?.longitude?.max ?? 1.767
344
+ }
345
+ }
276
346
  }