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

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 (99) hide show
  1. package/.public/javascripts/application.min.js +1 -1
  2. package/.public/javascripts/application.min.js.LICENSE.txt +7 -0
  3. package/.public/javascripts/application.min.js.map +1 -1
  4. package/.public/javascripts/shared.min.js +1 -1
  5. package/.public/javascripts/shared.min.js.LICENSE.txt +7 -0
  6. package/.public/javascripts/shared.min.js.map +1 -1
  7. package/.server/client/javascripts/file-upload.js +1 -0
  8. package/.server/client/javascripts/file-upload.js.map +1 -1
  9. package/.server/client/javascripts/geospatial-map.js +2 -28
  10. package/.server/client/javascripts/geospatial-map.js.map +1 -1
  11. package/.server/client/javascripts/govuk.js +2 -1
  12. package/.server/client/javascripts/govuk.js.map +1 -1
  13. package/.server/client/javascripts/location-map.js +3 -2
  14. package/.server/client/javascripts/location-map.js.map +1 -1
  15. package/.server/client/javascripts/map.d.ts +6 -0
  16. package/.server/client/javascripts/map.js +37 -0
  17. package/.server/client/javascripts/map.js.map +1 -1
  18. package/.server/server/plugins/engine/components/CheckboxesField.d.ts +20 -2
  19. package/.server/server/plugins/engine/components/CheckboxesField.js +24 -12
  20. package/.server/server/plugins/engine/components/CheckboxesField.js.map +1 -1
  21. package/.server/server/plugins/engine/components/EastingNorthingField.d.ts +5 -0
  22. package/.server/server/plugins/engine/components/EastingNorthingField.js +17 -0
  23. package/.server/server/plugins/engine/components/EastingNorthingField.js.map +1 -1
  24. package/.server/server/plugins/engine/components/FileUploadField.d.ts +10 -1
  25. package/.server/server/plugins/engine/components/FileUploadField.js +21 -7
  26. package/.server/server/plugins/engine/components/FileUploadField.js.map +1 -1
  27. package/.server/server/plugins/engine/components/GeospatialField.d.ts +21 -0
  28. package/.server/server/plugins/engine/components/GeospatialField.js +32 -9
  29. package/.server/server/plugins/engine/components/GeospatialField.js.map +1 -1
  30. package/.server/server/plugins/engine/components/LatLongField.d.ts +4 -0
  31. package/.server/server/plugins/engine/components/LocationFieldBase.js +4 -1
  32. package/.server/server/plugins/engine/components/LocationFieldBase.js.map +1 -1
  33. package/.server/server/plugins/engine/components/LocationFieldHelpers.d.ts +5 -1
  34. package/.server/server/plugins/engine/components/LocationFieldHelpers.js +10 -2
  35. package/.server/server/plugins/engine/components/LocationFieldHelpers.js.map +1 -1
  36. package/.server/server/plugins/engine/components/helpers/geospatial.d.ts +8 -1
  37. package/.server/server/plugins/engine/components/helpers/geospatial.js +56 -15
  38. package/.server/server/plugins/engine/components/helpers/geospatial.js.map +1 -1
  39. package/.server/server/plugins/engine/form-availability.d.ts +3 -2
  40. package/.server/server/plugins/engine/form-availability.js +3 -2
  41. package/.server/server/plugins/engine/form-availability.js.map +1 -1
  42. package/.server/server/plugins/engine/form-context.js +2 -2
  43. package/.server/server/plugins/engine/form-context.js.map +1 -1
  44. package/.server/server/plugins/engine/i18n/buildValidationMessages.d.ts +1 -1
  45. package/.server/server/plugins/engine/i18n/buildValidationMessages.js +30 -9
  46. package/.server/server/plugins/engine/i18n/buildValidationMessages.js.map +1 -1
  47. package/.server/server/plugins/engine/i18n/translations/cy.json +79 -13
  48. package/.server/server/plugins/engine/i18n/translations/en-GB.json +42 -13
  49. package/.server/server/plugins/engine/i18n/types.d.ts +1 -0
  50. package/.server/server/plugins/engine/i18n/types.js.map +1 -1
  51. package/.server/server/plugins/engine/models/unavailable-view-model.d.ts +11 -2
  52. package/.server/server/plugins/engine/models/unavailable-view-model.js +23 -4
  53. package/.server/server/plugins/engine/models/unavailable-view-model.js.map +1 -1
  54. package/.server/server/plugins/engine/pageControllers/FileUploadPageController.d.ts +6 -0
  55. package/.server/server/plugins/engine/pageControllers/FileUploadPageController.js +34 -1
  56. package/.server/server/plugins/engine/pageControllers/FileUploadPageController.js.map +1 -1
  57. package/.server/server/plugins/engine/pageControllers/validationOptions.d.ts +1 -1
  58. package/.server/server/plugins/engine/pageControllers/validationOptions.js +1 -1
  59. package/.server/server/plugins/engine/pageControllers/validationOptions.js.map +1 -1
  60. package/.server/server/plugins/engine/types.d.ts +4 -0
  61. package/.server/server/plugins/engine/types.js.map +1 -1
  62. package/.server/server/plugins/engine/unavailable-response.js +5 -2
  63. package/.server/server/plugins/engine/unavailable-response.js.map +1 -1
  64. package/.server/server/plugins/engine/views/components/_location-field-base.html +3 -2
  65. package/.server/server/plugins/engine/views/file-upload.html +1 -1
  66. package/.server/server/plugins/engine/views/unavailable.html +14 -11
  67. package/.server/server/utils/utils.d.ts +6 -0
  68. package/.server/server/utils/utils.js +18 -1
  69. package/.server/server/utils/utils.js.map +1 -1
  70. package/.server/server/utils/utils.test.js +21 -1
  71. package/.server/server/utils/utils.test.js.map +1 -1
  72. package/package.json +2 -1
  73. package/src/client/javascripts/file-upload.js +1 -0
  74. package/src/client/javascripts/geospatial-map.js +2 -31
  75. package/src/client/javascripts/govuk.js +2 -0
  76. package/src/client/javascripts/location-map.js +3 -1
  77. package/src/client/javascripts/map.js +42 -0
  78. package/src/server/plugins/engine/components/CheckboxesField.ts +34 -13
  79. package/src/server/plugins/engine/components/EastingNorthingField.ts +31 -0
  80. package/src/server/plugins/engine/components/FileUploadField.ts +29 -7
  81. package/src/server/plugins/engine/components/GeospatialField.ts +43 -11
  82. package/src/server/plugins/engine/components/LocationFieldBase.ts +3 -1
  83. package/src/server/plugins/engine/components/LocationFieldHelpers.ts +13 -3
  84. package/src/server/plugins/engine/components/helpers/geospatial.ts +84 -21
  85. package/src/server/plugins/engine/form-availability.ts +8 -2
  86. package/src/server/plugins/engine/form-context.ts +4 -2
  87. package/src/server/plugins/engine/i18n/buildValidationMessages.ts +15 -10
  88. package/src/server/plugins/engine/i18n/translations/cy.json +79 -13
  89. package/src/server/plugins/engine/i18n/translations/en-GB.json +42 -13
  90. package/src/server/plugins/engine/i18n/types.ts +1 -0
  91. package/src/server/plugins/engine/models/unavailable-view-model.ts +26 -5
  92. package/src/server/plugins/engine/pageControllers/FileUploadPageController.ts +42 -1
  93. package/src/server/plugins/engine/pageControllers/validationOptions.ts +2 -2
  94. package/src/server/plugins/engine/types.ts +4 -0
  95. package/src/server/plugins/engine/unavailable-response.ts +6 -2
  96. package/src/server/plugins/engine/views/components/_location-field-base.html +3 -2
  97. package/src/server/plugins/engine/views/file-upload.html +1 -1
  98. package/src/server/plugins/engine/views/unavailable.html +14 -11
  99. package/src/server/utils/utils.js +19 -1
@@ -16,15 +16,61 @@
16
16
  "numberMax": "Rhaid i {{#label}} fod yn {{#limit}} neu is",
17
17
  "maxWords": "Rhaid i {{#label}} fod yn {{#limit}} o eiriau neu lai",
18
18
  "unicode": "Mae {{#label}} yn cynnwys nodau annilys, er enghraifft, dashes hirion",
19
- "arrayMin": "Dewiswch o leiaf {{#limit}} o opsiynau o'r rhestr",
20
- "arrayMax": "Dim ond {{#limit}} y gellir eu dewis o'r rhestr",
21
- "arrayLength": "Dewiswch ddim ond {{#limit}} o opsiynau o'r rhestr",
22
- "featuresMin": "Diffiniwch o leiaf {{#limit}} nodwedd",
23
- "featuresMax": "Dim ond {{#limit}} nodwedd y gellir eu diffinio",
24
- "featuresLength": "Diffiniwch nodweddion {{#limit}} yn union",
25
- "filesMin": "Rhaid i chi uwchlwytho {{#limit}} o ffeiliau neu fwy",
26
- "filesMax": "Dim ond {{#limit}} o ffeiliau neu lai y gallwch eu huwchlwytho",
27
- "filesLength": "Rhaid i chi uwchlwytho'n union {{#limit}} o ffeiliau"
19
+ "arrayMin_zero": "Dewiswch o leiaf 1 opsiwn o'r rhestr",
20
+ "arrayMin_one": "Dewiswch o leiaf {{#limit}} opsiwn o'r rhestr",
21
+ "arrayMin_two": "Dewiswch o leiaf ddau opsiwn o'r rhestr",
22
+ "arrayMin_few": "Dewiswch o leiaf {{#limit}} opsiwn o'r rhestr",
23
+ "arrayMin_many": "Dewiswch o leiaf {{#limit}} opsiwn o'r rhestr",
24
+ "arrayMin_other": "Dewiswch o leiaf {{#limit}} opsiwn o'r rhestr",
25
+ "arrayMax_zero": "Dim ond {{#limit}} opsiynau y gellir eu dewis o'r rhestr",
26
+ "arrayMax_one": "Dim ond {{#limit}} opsiwn y gellir ei ddewis o'r rhestr",
27
+ "arrayMax_two": "Dim ond dwy opsiwn y gellir eu dewis o'r rhestr",
28
+ "arrayMax_few": "Dim ond {{#limit}} opsiwn y gellir eu dewis o'r rhestr",
29
+ "arrayMax_many": "Dim ond {{#limit}} opsiwn y gellir eu dewis o'r rhestr",
30
+ "arrayMax_other": "Dim ond {{#limit}} opsiwn y gellir eu dewis o'r rhestr",
31
+ "arrayLength_zero": "Dewiswch 0 opsiwn yn unig o'r rhestr",
32
+ "arrayLength_one": "Dewiswch un opsiwn yn unig o'r rhestr",
33
+ "arrayLength_two": "Dewiswch {{#limit}} opsiwn yn unig o'r rhestr",
34
+ "arrayLength_few": "Dewiswch {{#limit}} opsiwn yn unig o'r rhestr",
35
+ "arrayLength_many": "Dewiswch {{#limit}} opsiwn yn unig o'r rhestr",
36
+ "arrayLength_other": "Dewiswch {{#limit}} opsiwn yn unig o'r rhestr",
37
+
38
+ "featuresMin_zero": "Diffiniwch o leiaf {{#limit}} nodwedd",
39
+ "featuresMin_one": "Diffiniwch o leiaf un nodwedd",
40
+ "featuresMin_two": "Diffiniwch o leiaf {{#limit}} nodwedd",
41
+ "featuresMin_few": "Diffiniwch o leiaf {{#limit}} nodwedd",
42
+ "featuresMin_many": "Diffiniwch o leiaf {{#limit}} nodwedd",
43
+ "featuresMin_other": "Diffiniwch o leiaf {{#limit}} nodwedd",
44
+ "featuresMax_zero": "Dim ond {{#limit}} nodwedd y gellir eu diffinio",
45
+ "featuresMax_one": "Dim ond {{#limit}} nodwedd y gellir ei diffinio",
46
+ "featuresMax_two": "Dim ond {{#limit}} nodwedd y gellir eu diffinio",
47
+ "featuresMax_few": "Dim ond {{#limit}} nodwedd y gellir eu diffinio",
48
+ "featuresMax_many": "Dim ond {{#limit}} nodwedd y gellir eu diffinio",
49
+ "featuresMax_other": "Dim ond {{#limit}} nodwedd y gellir eu diffinio",
50
+ "featuresLength_zero": "Diffiniwch yn union {{#limit}} nodwedd",
51
+ "featuresLength_one": "Diffiniwch un nodwedd yn union",
52
+ "featuresLength_two": "Diffiniwch nodweddion {{#limit}} yn union",
53
+ "featuresLength_few": "Diffiniwch nodweddion {{#limit}} yn union",
54
+ "featuresLength_many": "Diffiniwch nodweddion {{#limit}} yn union",
55
+ "featuresLength_other": "Diffiniwch nodweddion {{#limit}} yn union",
56
+ "filesMin_zero": "Rhaid i chi uwchlwytho {{#limit}} ffeil neu fwy",
57
+ "filesMin_one": "Rhaid i chi uwchlwytho un ffeil neu fwy",
58
+ "filesMin_two": "Rhaid i chi uwchlwytho {{#limit}} o ffeiliau neu fwy",
59
+ "filesMin_few": "Rhaid i chi uwchlwytho {{#limit}} o ffeiliau neu fwy",
60
+ "filesMin_many": "Rhaid i chi uwchlwytho {{#limit}} o ffeiliau neu fwy",
61
+ "filesMin_other": "Rhaid i chi uwchlwytho {{#limit}} o ffeiliau neu fwy",
62
+ "filesMax_zero": "Dim ond {{#limit}} ffeil neu lai y gallwch eu huwchlwytho",
63
+ "filesMax_one": "Dim ond un ffeil neu lai y gallwch ei huwchlwytho",
64
+ "filesMax_two": "Dim ond {{#limit}} o ffeiliau neu lai y gallwch eu huwchlwytho",
65
+ "filesMax_few": "Dim ond {{#limit}} o ffeiliau neu lai y gallwch eu huwchlwytho",
66
+ "filesMax_many": "Dim ond {{#limit}} o ffeiliau neu lai y gallwch eu huwchlwytho",
67
+ "filesMax_other": "Dim ond {{#limit}} o ffeiliau neu lai y gallwch eu huwchlwytho",
68
+ "filesLength_zero": "Rhaid i chi uwchlwytho union {{#limit}} ffeil",
69
+ "filesLength_one": "Rhaid i chi uwchlwytho union un ffeil",
70
+ "filesLength_two": "Rhaid i chi uwchlwytho'n union {{#limit}} o ffeiliau",
71
+ "filesLength_few": "Rhaid i chi uwchlwytho'n union {{#limit}} o ffeiliau",
72
+ "filesLength_many": "Rhaid i chi uwchlwytho'n union {{#limit}} o ffeiliau",
73
+ "filesLength_other": "Rhaid i chi uwchlwytho'n union {{#limit}} o ffeiliau"
28
74
  },
29
75
 
30
76
  "errors": {
@@ -44,7 +90,7 @@
44
90
  "and": "a",
45
91
  "england": "Lloegr",
46
92
  "wales": "Cymru",
47
- "northernIreland": "Gogledd Iwerddon",
93
+ "northern-ireland": "Gogledd Iwerddon",
48
94
  "scotland": "Yr Alban",
49
95
  "sendFeedback": "Anfon adborth"
50
96
  },
@@ -129,7 +175,13 @@
129
175
  "removeFileTitle": "Ydych chi'n siŵr eich bod chi eisiau dileu'r ffeil hon?",
130
176
  "removeFileBody": "Ni allwch adfer ffeiliau a dynnwyd.",
131
177
  "removeFileButton": "Dileu ffeil",
132
- "cancel": "Canslo"
178
+ "cancel": "Canslo",
179
+ "FILE_VIRUS": "Mae'r ffeil a ddewiswyd yn cynnwys firws",
180
+ "FILE_EMPTY": "Mae'r ffeil a ddewiswyd yn wag",
181
+ "FILE_TOO_LARGE": "Rhaid i'r ffeil a ddewiswyd fod yn llai na [[maxFileSizeFormatted]]",
182
+ "FILE_INVALID_TYPE": "Rhaid i'r ffeil a ddewiswyd fod yn [[fileExtensions]]",
183
+ "FILE_UPLOAD_FAILED": "Ni ellid uwchlwytho'r ffeil a ddewiswyd - rhowch gynnig arall arni",
184
+ "FILE_ERROR_UNKNOWN": "Gwall anhysbys"
133
185
  },
134
186
 
135
187
  "exit": {
@@ -155,6 +207,16 @@
155
207
  "bannerForce": "Rhagolwg o ffurflen [[previewMode]] yw hon. Peidiwch â rhoi gwybodaeth bersonol.",
156
208
  "bannerText": "Dyma ragolwg o dudalen ffurflen [[previewMode]] rydych chi'n ei golygu.",
157
209
  "previousPages": "Mae'n dibynnu ar atebion o dudalennau cynharach yn y ffurflen. Yn y fersiwn fyw, bydd angen i ddefnyddwyr gwblhau'r cwestiynau hynny yn gyntaf."
210
+ },
211
+
212
+ "formUnavailable": {
213
+ "title": "Mae'n ddrwg gennyf, nid yw'r ffurflen hon ar gael",
214
+ "subHeading": "Nid yw '[[formTitle]]' ar gael mwyach.",
215
+ "contactDetailsHeading": "Manylion cyswllt ar gyfer [[organisationName]]",
216
+ "telephone": "Ffôn",
217
+ "callCharges": "Dysgwch am gostau galwadau",
218
+ "email": "E-bost",
219
+ "onlineContactForm": "Ffurflen gyswllt ar-lein"
158
220
  }
159
221
  },
160
222
 
@@ -244,7 +306,8 @@
244
306
  "eastingDigits": "Rhaid i {{#label}} ar gyfer [[fieldLabel]] fod rhwng 1 a 6 digid",
245
307
  "northingDigits": "Rhaid i {{#label}} ar gyfer [[fieldLabel]] fod rhwng 1 a 7 digid",
246
308
  "eastingRange": "Rhaid i {{#label}} ar gyfer [[fieldLabel]] fod rhwng [[min]] a [[max]]",
247
- "northingRange": "Rhaid i {{#label}} ar gyfer [[fieldLabel]] fod rhwng [[min]] a [[max]]"
309
+ "northingRange": "Rhaid i {{#label}} ar gyfer [[fieldLabel]] fod rhwng [[min]] a [[max]]",
310
+ "wrongCountry": "Rhaid i leoliad fod y tu mewn i [[country]]"
248
311
  },
249
312
 
250
313
  "nationalGridField": {
@@ -319,7 +382,10 @@
319
382
  "filesCount_two": "Uwchlwythwyd [[count]] ffeil",
320
383
  "filesCount_few": "Uwchlwythwyd [[count]] ffeil",
321
384
  "filesCount_many": "Uwchlwythwyd [[count]] o ffeiliau",
322
- "filesCount_other": "Uwchlwythwyd [[count]] ffeil"
385
+ "filesCount_other": "Uwchlwythwyd [[count]] ffeil",
386
+ "chooseFile": "Dewiswch ffeil",
387
+ "dropFile": "neu ollwng ffeil",
388
+ "noFileChosen": "Dim ffeil wedi'i dewis"
323
389
  },
324
390
 
325
391
  "characterCount": {
@@ -16,15 +16,24 @@
16
16
  "numberMax": "{{#label}} must be {{#limit}} or lower",
17
17
  "maxWords": "{{#label}} must be {{#limit}} words or fewer",
18
18
  "unicode": "{{#label}} includes invalid characters, for example, long dashes",
19
- "arrayMin": "Select at least {{#limit}} options from the list",
20
- "arrayMax": "Only {{#limit}} can be selected from the list",
21
- "arrayLength": "Select only {{#limit}} options from the list",
22
- "featuresMin": "Define at least {{#limit}} features",
23
- "featuresMax": "Only {{#limit}} features can be defined",
24
- "featuresLength": "Define exactly {{#limit}} features",
25
- "filesMin": "You must upload {{#limit}} files or more",
26
- "filesMax": "You can only upload {{#limit}} files or less",
27
- "filesLength": "You must upload exactly {{#limit}} files"
19
+ "arrayMin_one": "Select at least {{#limit}} option from the list",
20
+ "arrayMin_other": "Select at least {{#limit}} options from the list",
21
+ "arrayMax_one": "Only {{#limit}} option can be selected from the list",
22
+ "arrayMax_other": "Only {{#limit}} options can be selected from the list",
23
+ "arrayLength_one": "Select only {{#limit}} option from the list",
24
+ "arrayLength_other": "Select only {{#limit}} options from the list",
25
+ "featuresMin_one": "Define at least {{#limit}} feature",
26
+ "featuresMin_other": "Define at least {{#limit}} features",
27
+ "featuresMax_one": "Only {{#limit}} feature can be defined",
28
+ "featuresMax_other": "Only {{#limit}} features can be defined",
29
+ "featuresLength_one": "Define exactly {{#limit}} feature",
30
+ "featuresLength_other": "Define exactly {{#limit}} features",
31
+ "filesMin_one": "You must upload {{#limit}} file or more",
32
+ "filesMin_other": "You must upload {{#limit}} files or more",
33
+ "filesMax_one": "You can only upload {{#limit}} file or less",
34
+ "filesMax_other": "You can only upload {{#limit}} files or less",
35
+ "filesLength_one": "You must upload exactly {{#limit}} file",
36
+ "filesLength_other": "You must upload exactly {{#limit}} files"
28
37
  },
29
38
 
30
39
  "errors": {
@@ -44,7 +53,7 @@
44
53
  "and": "and",
45
54
  "england": "England",
46
55
  "wales": "Wales",
47
- "northernIreland": "Northern Ireland",
56
+ "northern-ireland": "Northern Ireland",
48
57
  "scotland": "Scotland",
49
58
  "sendFeedback": "Send feedback"
50
59
  },
@@ -113,7 +122,13 @@
113
122
  "removeFileTitle": "Are you sure you want to remove this file?",
114
123
  "removeFileBody": "You cannot recover removed files.",
115
124
  "removeFileButton": "Remove file",
116
- "cancel": "Cancel"
125
+ "cancel": "Cancel",
126
+ "FILE_VIRUS": "The selected file contains a virus",
127
+ "FILE_EMPTY": "The selected file is empty",
128
+ "FILE_TOO_LARGE": "The selected file must be smaller than [[maxFileSizeFormatted]]",
129
+ "FILE_INVALID_TYPE": "The selected file must be a [[fileExtensions]]",
130
+ "FILE_UPLOAD_FAILED": "The selected file could not be uploaded - try again",
131
+ "FILE_ERROR_UNKNOWN": "Unknown error"
117
132
  },
118
133
 
119
134
  "exit": {
@@ -139,6 +154,16 @@
139
154
  "bannerForce": "This is a preview of a [[previewMode]] form. Do not enter personal information.",
140
155
  "bannerText": "This is a preview of a [[previewMode]] form page you are editing.",
141
156
  "previousPages": "It depends on answers from earlier pages in the form. In the live version, users will need to complete those questions first."
157
+ },
158
+
159
+ "formUnavailable": {
160
+ "title": "Sorry, this form is unavailable",
161
+ "subHeading": "'[[formTitle]]' is no longer available.",
162
+ "contactDetailsHeading": "Contact details for [[organisationName]]",
163
+ "telephone": "Telephone",
164
+ "callCharges": "Find out about call charges",
165
+ "email": "Email",
166
+ "onlineContactForm": "Online contact form"
142
167
  }
143
168
  },
144
169
 
@@ -224,7 +249,8 @@
224
249
  "eastingDigits": "{{#label}} for [[fieldLabel]] must be between 1 and 6 digits",
225
250
  "northingDigits": "{{#label}} for [[fieldLabel]] must be between 1 and 7 digits",
226
251
  "eastingRange": "{{#label}} for [[fieldLabel]] must be between [[min]] and [[max]]",
227
- "northingRange": "{{#label}} for [[fieldLabel]] must be between [[min]] and [[max]]"
252
+ "northingRange": "{{#label}} for [[fieldLabel]] must be between [[min]] and [[max]]",
253
+ "wrongCountry": "Location must be within [[country]]"
228
254
  },
229
255
 
230
256
  "nationalGridField": {
@@ -291,7 +317,10 @@
291
317
  "uploadFailed": "There was a problem with your uploaded files. Re-upload them before submitting the form again.",
292
318
  "uploadedFilesHeading": "Uploaded files",
293
319
  "filesCount_one": "[[count]] file uploaded",
294
- "filesCount_other": "[[count]] files uploaded"
320
+ "filesCount_other": "[[count]] files uploaded",
321
+ "chooseFile": "Choose file",
322
+ "dropFile": "or drop file",
323
+ "noFileChosen": "No file chosen"
295
324
  },
296
325
 
297
326
  "characterCount": {
@@ -24,6 +24,7 @@ export type FormDefinitionTranslations = Record<
24
24
  shortDescription: string
25
25
  errorDescription: string
26
26
  paymentDescription: string
27
+ instructionText: string
27
28
  }>
28
29
  >
29
30
  sections: Record<string, Partial<Pick<Section, 'title'>>>
@@ -1,19 +1,40 @@
1
- import { type FormMetadata, type FormMetadataContact } from '@defra/forms-model'
1
+ import {
2
+ type FormDefinition,
3
+ type FormMetadata,
4
+ type FormMetadataContact
5
+ } from '@defra/forms-model'
6
+
7
+ import { createFormTranslator } from '../i18n/createFormTranslator.js'
8
+ import { getAvailableLanguages } from '../i18n/languages.js'
9
+ import { type Translator } from '../types/index.js'
2
10
 
3
11
  export interface UnavailableViewModel {
4
12
  pageTitle: string
5
13
  formTitle: string
6
14
  organisationName: string
7
15
  contact?: FormMetadataContact
16
+ context: { translator: Translator }
17
+ language: string
18
+ languages: { code: string; name: string }[]
8
19
  }
9
20
 
10
21
  export function unavailableViewModel(
11
- metadata: FormMetadata
22
+ metadata: FormMetadata,
23
+ definition: FormDefinition | undefined,
24
+ language: string
12
25
  ): UnavailableViewModel {
26
+ const translator = createFormTranslator(metadata, definition, language)
27
+ const { t, tForm } = translator
13
28
  return {
14
- pageTitle: 'Sorry, this form is unavailable',
15
- formTitle: metadata.title,
29
+ pageTitle: t('pages.formUnavailable.title'),
30
+ formTitle: tForm('title') || metadata.title,
16
31
  organisationName: metadata.organisation,
17
- contact: metadata.contact
32
+ contact: metadata.contact,
33
+ context: { translator },
34
+ language,
35
+ // Always get Welsh and English
36
+ languages: getAvailableLanguages({
37
+ metadata: { translations: { cy: {} } }
38
+ } as unknown as FormDefinition)
18
39
  }
19
40
  }
@@ -42,6 +42,7 @@ import {
42
42
  type FormRequestPayload,
43
43
  type FormResponseToolkit
44
44
  } from '../../../routes/types.js'
45
+ import { joinWithOr } from '../../../utils/utils.js'
45
46
 
46
47
  const MAX_UPLOADS = 25
47
48
  const CDP_UPLOAD_TIMEOUT_MS = 60000 // 1 minute
@@ -285,6 +286,13 @@ export class FileUploadPageController extends QuestionPageController {
285
286
  summaryList: formComponent.model.upload?.summaryList ?? { rows: [] },
286
287
  uploadingLabel: t('components.fileUploadField.uploading')
287
288
  }
289
+ formComponent.model = {
290
+ ...formComponent.model,
291
+ javascript: true,
292
+ chooseFilesButtonText: t('components.fileUploadField.chooseFile'),
293
+ dropInstructionText: t('components.fileUploadField.dropFile'),
294
+ noFileChosenText: t('components.fileUploadField.noFileChosen')
295
+ }
288
296
 
289
297
  const index = components.indexOf(formComponent)
290
298
 
@@ -451,6 +459,9 @@ export class FileUploadPageController extends QuestionPageController {
451
459
 
452
460
  const allErrors: FormSubmissionError[] = []
453
461
 
462
+ const translator = this.getTranslator(request)
463
+ const { t } = translator
464
+
454
465
  for (const file of uploadedFiles) {
455
466
  if (file.fileStatus === FileStatus.complete) {
456
467
  const perFileState: FileState = {
@@ -465,7 +476,14 @@ export class FileUploadPageController extends QuestionPageController {
465
476
  // Collect the error for rejected/pending files.
466
477
  const { fileUpload } = this
467
478
  const name = fileUpload.name
468
- const text = file.errorMessage ?? 'Unknown error'
479
+ const errorParams = this.expandErrorParams(
480
+ file.errorParams,
481
+ t('common.or')
482
+ )
483
+ const text = t(
484
+ `pages.fileUpload.${file.errorCode ?? 'FILE_ERROR_UNKNOWN'}`,
485
+ errorParams
486
+ )
469
487
  allErrors.push({ path: [name], href: `#${name}`, name, text })
470
488
  }
471
489
  }
@@ -482,6 +500,29 @@ export class FileUploadPageController extends QuestionPageController {
482
500
  }
483
501
  }
484
502
 
503
+ /**
504
+ * Process the error parameters so any arrays get expanded (joined), ready to be passed into the error message
505
+ * @param errorParams - received from the file upload (may be a number, a string, or a string array)
506
+ * @param finalSeparator - 'or' in English, and 'neu' in Welsh
507
+ */
508
+ private expandErrorParams(
509
+ errorParams: Record<string, number | string | string[]> | undefined,
510
+ finalSeparator: string
511
+ ) {
512
+ if (!errorParams) {
513
+ return {}
514
+ }
515
+ const expanded = {} as Record<string, number | string>
516
+ for (const [key, value] of Object.entries(errorParams)) {
517
+ if (Array.isArray(value)) {
518
+ expanded[key] = joinWithOr(value, finalSeparator)
519
+ } else {
520
+ expanded[key] = value
521
+ }
522
+ }
523
+ return expanded
524
+ }
525
+
485
526
  /**
486
527
  * Checks the payload for a file getting removed
487
528
  * and removes it from the upload files if found
@@ -26,7 +26,7 @@ export const opts = {
26
26
  * import messageTemplate directly and get the English version.
27
27
  */
28
28
  export const messageTemplate: ValidationMessages = buildValidationMessages(
29
- (key) => t(key, 'en-GB')
29
+ (key, options) => t(key, 'en-GB', options)
30
30
  )
31
31
 
32
32
  export const messages: LanguageMessagesExt = {
@@ -79,7 +79,7 @@ export const messagesPre: LanguageMessages =
79
79
  messages as unknown as LanguageMessages
80
80
 
81
81
  export function buildLanguageMessages(
82
- t: (key: string) => string
82
+ t: (key: string, options?: Record<string, unknown>) => string
83
83
  ): LanguageMessages {
84
84
  const vm = buildValidationMessages(t)
85
85
  return {
@@ -245,11 +245,15 @@ export type FileUpload = {
245
245
  } & (
246
246
  | {
247
247
  fileStatus: FileStatus.complete | FileStatus.rejected | FileStatus.pending
248
+ errorCode?: string
248
249
  errorMessage?: string
250
+ errorParams?: Record<string, number | string | string[]>
249
251
  }
250
252
  | {
251
253
  fileStatus: FileStatus.complete
254
+ errorCode?: string
252
255
  errorMessage?: undefined
256
+ errorParams?: Record<string, number | string | string[]>
253
257
  }
254
258
  )
255
259
 
@@ -2,6 +2,8 @@ import { type Request, type ResponseToolkit, type Server } from '@hapi/hapi'
2
2
 
3
3
  import { isOfflineBoom } from './form-availability.js'
4
4
  import { unavailableViewModel } from './models/unavailable-view-model.js'
5
+ import { type AnyFormRequest } from './types.js'
6
+ import { resolveLanguage } from '../../utils/utils.js'
5
7
 
6
8
  /**
7
9
  * Registers a server-wide onPreResponse extension that intercepts the offline
@@ -17,10 +19,12 @@ export function registerUnavailableResponse(server: Server) {
17
19
  return h.continue
18
20
  }
19
21
 
20
- const { metadata } = response.data
22
+ const { metadata, definition } = response.data
23
+
24
+ const language = resolveLanguage(request as unknown as AnyFormRequest)
21
25
 
22
26
  return h
23
- .view('unavailable', unavailableViewModel(metadata))
27
+ .view('unavailable', unavailableViewModel(metadata, definition, language))
24
28
  .header('Cache-Control', 'no-store, no-cache, must-revalidate')
25
29
  .header('X-Robots-Tag', 'noindex, nofollow')
26
30
  .code(200)
@@ -61,7 +61,7 @@
61
61
  {% set detailsHtml %}
62
62
  {% if component.model.instructionText %}
63
63
  {{ govukDetails({
64
- summaryText: t('components.locationFieldBase.howToFind'),
64
+ summaryText: component.model.instructionSummary,
65
65
  html: component.model.instructionText | markdown | safe,
66
66
  classes: "govuk-!-margin-top-3"
67
67
  }) }}
@@ -70,8 +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 }}"
73
+ <div id="{{component.model.name}}" class="govuk-form-group app-location-field {{ "govuk-form-group--error" if hasErrors }}"
74
74
  data-locationtype="{{component.type | lower}}"
75
+ data-country="{{component.model.country}}"
75
76
  data-maplayers="{{component.model.mapLayers}}">
76
77
  {{ govukFieldset({
77
78
  legend: {
@@ -15,7 +15,7 @@
15
15
  {% if formAction %}
16
16
  {{ govukButton({
17
17
  text: t('pages.fileUpload.upload'),
18
- classes: "govuk-button--secondary upload-file-button",
18
+ classes: "govuk-button--secondary upload-file-button js-hidden",
19
19
  preventDoubleClick: true,
20
20
  disabled: context.isForceAccess
21
21
  }) }}
@@ -1,32 +1,35 @@
1
1
  {% extends baseLayoutPath %}
2
2
 
3
+ {% set t = context.translator.t %}
4
+ {% set tForm = context.translator.tForm %}
5
+
3
6
  {% block content %}
4
7
  <div class="govuk-grid-row">
5
8
  <div class="govuk-grid-column-two-thirds">
6
- <h1 class="govuk-heading-l">Sorry, this form is unavailable</h1>
7
- <p class="govuk-body">'{{ formTitle }}' is no longer available.</p>
8
- <h2 class="govuk-heading-m">Contact details for {{ organisationName }}</h2>
9
+ <h1 class="govuk-heading-l">{{ t('pages.formUnavailable.title') }}</h1>
10
+ <p class="govuk-body">{{ t('pages.formUnavailable.subHeading', { formTitle: formTitle }) }}</p>
11
+ <h2 class="govuk-heading-m">{{ t('pages.formUnavailable.contactDetailsHeading', { organisationName: organisationName }) }}</h2>
9
12
 
10
13
  {% if contact.phone %}
11
- <h3 class="govuk-heading-s">Telephone</h3>
14
+ <h3 class="govuk-heading-s">{{ t('pages.formUnavailable.telephone') }}</h3>
12
15
  <div class="app-prose-scope">
13
- {{ contact.phone | markdown(3) | safe }}
16
+ {{ tForm('contact.phone') | markdown(3) | safe }}
14
17
  </div>
15
- <p class="govuk-body"><a href="https://www.gov.uk/call-charges" class="govuk-link govuk-link--no-visited-state">Find out about call charges</a></p>
18
+ <p class="govuk-body"><a href="https://www.gov.uk/call-charges" class="govuk-link govuk-link--no-visited-state">{{ t('pages.formUnavailable.callCharges') }}</a></p>
16
19
  {% endif %}
17
20
 
18
21
  {% if contact.email %}
19
- <h3 class="govuk-heading-s">Email</h3>
22
+ <h3 class="govuk-heading-s">{{ t('pages.formUnavailable.email') }}</h3>
20
23
  <ul class="govuk-list">
21
- <li><a class="govuk-link govuk-link--no-visited-state" href="mailto:{{ contact.email.address }}">{{ contact.email.address }}</a></li>
22
- <li>{{ contact.email.responseTime }}</li>
24
+ <li><a class="govuk-link govuk-link--no-visited-state" href="mailto:{{ tForm('contact.email.address') }}">{{ tForm('contact.email.address') }}</a></li>
25
+ <li>{{ tForm('contact.email.responseTime') }}</li>
23
26
  </ul>
24
27
  {% endif %}
25
28
 
26
29
  {% if contact.online %}
27
- <h3 class="govuk-heading-s">Online contact form</h3>
30
+ <h3 class="govuk-heading-s">{{ t('pages.formUnavailable.onlineContactForm') }}</h3>
28
31
  <ul class="govuk-list">
29
- <li><a class="govuk-link govuk-link--no-visited-state" href="{{ contact.online.url }}">{{ contact.online.text }}</a></li>
32
+ <li><a class="govuk-link govuk-link--no-visited-state" href="{{ tForm('contact.online.url') }}">{{ tForm('contact.online.text') }}</a></li>
30
33
  </ul>
31
34
  {% endif %}
32
35
  </div>
@@ -44,6 +44,24 @@ export function resolveLanguage(request) {
44
44
  }
45
45
 
46
46
  /**
47
- * @import { FormMetadata } from '@defra/forms-model'
47
+ * Create a comma-separated list with the last seperator being 'or'
48
+ * @param { string[] | undefined } items
49
+ * @param {string} [finalSeparator]
50
+ */
51
+ export function joinWithOr(items, finalSeparator = 'or') {
52
+ if (!items || items.length === 0) {
53
+ return ''
54
+ }
55
+ if (items.length === 1) {
56
+ return items[0]
57
+ }
58
+ if (items.length === 2) {
59
+ return `${items[0]} ${finalSeparator} ${items[1]}`
60
+ }
61
+
62
+ return `${items.slice(0, -1).join(', ')} ${finalSeparator} ${items.at(-1)}`
63
+ }
64
+
65
+ /**
48
66
  * @import { AnyFormRequest } from '../plugins/engine/types.js'
49
67
  */