@opengeoweb/sigmet-airmet 9.24.0 → 9.25.2

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.
package/index.esm.js CHANGED
@@ -3,32 +3,515 @@ import * as React from 'react';
3
3
  import React__default from 'react';
4
4
  import { FormControlLabel, Radio, Grid, Typography, Box, Button, Checkbox, MenuItem, FormHelperText, useTheme, Dialog, DialogTitle, DialogContent, Card, LinearProgress, List, ListItemButton, Backdrop, CircularProgress } from '@mui/material';
5
5
  import { useFormContext } from 'react-hook-form';
6
- import { useDraftFormHelpers, ReactHookFormRadioGroup, hasValidGeometry, ReactHookFormSelect, ReactHookFormNumberField, isInteger, isValidMax, isValidMin, isEmpty, ReactHookFormDateTime, countIntersectionPoints, hasMulitpleIntersections, ReactHookFormHiddenInput, isMaximumOneDrawing, hasIntersectionWithFIR, isValidGeoJsonCoordinates, isXHoursBefore, isXHoursAfter, ReactHookFormTextField, isLatitude, isNonOrBothCoordinates, isLongitude, ReactHookFormFormControl, isGeometryDirty, ReactHookFormProvider, defaultFormOptions } from '@opengeoweb/form-fields';
6
+ import { FORM_FIELDS_NAMESPACE, useDraftFormHelpers, ReactHookFormRadioGroup, hasValidGeometry, ReactHookFormSelect, ReactHookFormNumberField, isInteger, isValidMax, isValidMin, isEmpty, ReactHookFormDateTime, countIntersectionPoints, hasMulitpleIntersections, ReactHookFormHiddenInput, isMaximumOneDrawing, isValidGeoJsonCoordinates, hasIntersectionWithFIR, isXHoursBefore, isXHoursAfter, ReactHookFormTextField, isLatitude, isNonOrBothCoordinates, isLongitude, ReactHookFormFormControl, isGeometryDirty, ReactHookFormProvider, defaultFormOptions } from '@opengeoweb/form-fields';
7
7
  import { useApiContext, useApi, createApiInstance, createNonAuthApiInstance, createFakeApiInstance, ApiProvider } from '@opengeoweb/api';
8
8
  import { defaultGeoJSONStyleProperties, defaultIntersectionStyleProperties, defaultPoint, addGeoJSONProperties, defaultBox, defaultPolygon, DRAWMODE, addSelectionTypeToGeoJSON, defaultDelete, getIcon, MapControls, MapViewLayer, useMapDrawTool, addFeatureProperties, rewindGeometry } from '@opengeoweb/webmap-react';
9
+ import i18n from 'i18next';
10
+ import { useTranslation } from 'react-i18next';
9
11
  import { dateUtils, ToggleMenu, CustomTooltip, useIsMounted, StatusTag, AlertBanner, ConfirmationServiceProvider, usePreventBrowserClose, useConfirmationDialog, isAxiosError, getAxiosErrorMessage, usePoller, ErrorBoundary } from '@opengeoweb/shared';
12
+ import { LayerManagerMapButtonConnect, LegendMapButtonConnect, MultiDimensionSelectMapButtonsConnect, MapViewConnect, TimeSliderConnect, LegendConnect, LayerManagerConnect } from '@opengeoweb/core';
10
13
  import { DrawFIRLand, ChevronLeft, Edit, Success, Clock } from '@opengeoweb/theme';
11
14
  import { LayerType, webmapUtils } from '@opengeoweb/webmap';
12
15
  import { debounce } from 'lodash';
13
16
  import { useDispatch, useSelector, shallowEqual } from 'react-redux';
14
17
  import { mapSelectors, syncGroupsActions, mapStoreActions, defaultLayers, syncConstants } from '@opengeoweb/store';
15
- import { LayerManagerMapButtonConnect, LegendMapButtonConnect, MultiDimensionSelectMapButtonsConnect, MapViewConnect, TimeSliderConnect, LegendConnect, LayerManagerConnect } from '@opengeoweb/core';
16
- import { useAuthenticationContext } from '@opengeoweb/authentication';
17
18
  import { Box as Box$1 } from '@mui/system';
18
- import 'i18next';
19
- import 'react-i18next';
19
+ import { useAuthenticationContext } from '@opengeoweb/authentication';
20
20
 
21
21
  var en = {
22
- "sigmet-airmet": "sigmet"
22
+ "sigmet-airmet": "sigmet",
23
+ levels: "Levels",
24
+ "not-published": "(Not published)",
25
+ "valid-time": "Valid time",
26
+ "vulcanic-ash-description": "Use the FIR to indicate the direction the Volcanic Ash is moving to",
27
+ "vulcanic-VA-SIGMET-text": "Cancel VA SIGMET without VA MOV TO information",
28
+ "vulcanic-cloud-moving-text": "Volcanic Cloud is moving in the direction of",
29
+ unknown: "Unknown",
30
+ "create-new-product": "Create a new {{ product }}",
31
+ discard: "DISCARD",
32
+ save: "Save",
33
+ cancel: "Cancel",
34
+ publish: "Publish",
35
+ back: "BACK",
36
+ draft: "DRAFT",
37
+ "error-title": "Something went wrong with loading the configuration file",
38
+ "error-auth-login": "This feature is protected by authentication. Please log in to proceed",
39
+ "error-config": "An error has occurred while loading the config",
40
+ "error-backend": "An error has occurred while retrieving the list, please try again",
41
+ "error-auth": "This feature is protected by authentication",
42
+ "saved-as-draft": "saved as draft",
43
+ cancels: "Cancels",
44
+ close: "Close",
45
+ "discard-non-capitalized": "Discard",
46
+ "are-you-sure-you-want-to-discard": "Are you sure you would like to discard this {{product}}? Its properties will be lost`",
47
+ "save-changes-made": "Do you want to save any changes made?",
48
+ "publish-this-product": "Are you sure you want to publish this {{product}}?",
49
+ "cancel-this-product": "Are you sure you want to cancel this {{product}}?`",
50
+ "save-and-close": "Save and close",
51
+ "discard-and-close": "Discard and close",
52
+ "drop-a-point-as": "Drop a point as {{type}} position`",
53
+ "draw-a-box-as": "Draw a box as {{type}} position",
54
+ "draw-a-shape-as": "Draw a shape as {{type}} position`",
55
+ "set-a-fir-as": "Set FIR as {{type}} position`",
56
+ "remove-geometry": "Remove geometry",
57
+ "valid-until-time": "Valid until time has to be after Valid from time",
58
+ "discard-product": "Discard {{product}}",
59
+ "issue-time": "Issue time",
60
+ "type-title": "Type",
61
+ "phenomenon-title": "What",
62
+ "observation-label": "Observed",
63
+ "forecast-label": "Forecast",
64
+ "valid-from-before-current-error": "Valid from time cannot be before current time",
65
+ "valid-from-time-error": "Valid from time can be no more than {{hours}} hours after current time",
66
+ "date-and-time": "Date and time",
67
+ "valid-from": "Valid from",
68
+ "valid-until": "Valid until",
69
+ "valid-until-time-error": "Valid until time can be no more than {{hours}} hours after Valid from time",
70
+ "select-fir-title": "Where",
71
+ "select-fir-label": "Select FIR",
72
+ "geometry-coodinates-empty-message": "A start position drawing is required",
73
+ "geometry-no-intersection-message": "The start position needs to be (partly) inside the FIR",
74
+ "geometry-exit-draw-mode-message": "Press ESC to exit draw mode",
75
+ "geometry-max-feature-points-message": "Intersection of the drawn polygon with the FIR-boundary has more than 6 individual points. Check if the TAC in the preview corresponds to the intended area.",
76
+ "geometry-multi-intersections-message": "The drawn polygon has multiple intersections with the FIR-boundary. The drawn polygon will be used for the TAC-code.",
77
+ "geometry-maximum-points-message": "The start position drawing allows a maximum of {{maxPoints}} individual points",
78
+ "geometry-more-than-6-points-message": "The start/end position drawing has exceeded 6 individual points. The TAC has a total of {{totalDrawnPoints}} points. If possible, reduce the number of points.",
79
+ "geometry-intersection-above-6-points-message": "The start/end position of the intersected polygon has {{intersectingPolygonPointsTotal}} points, and the intersection of the drawn polygon with the FIR-boundary has exceeded 6 individual points. Check if the TAC in the preview corresponds to the intended area.",
80
+ "geometry-only-one-start-position-drawing": "Only one start position drawing is allowed",
81
+ "progress-get-movement-step-valktmessage": "Speed should be rounded to the nearest {{value}}kt",
82
+ "progress-get-movement-step-valkmhmessage": "Speed should be rounded to the nearest {{value}}kmh",
83
+ "progress-coordinate-empty-message": "An end position drawing is required when selecting End position",
84
+ "progress-no-intersection-message": "The end position needs to be (partly) inside the FIR",
85
+ "invalid-unit": "Invalid unit",
86
+ "progress-maximumPointsMessage": "The end position drawing allows a maximum of {{maxPoints}} individual points",
87
+ "progress-more-than-6-points-message": "The start/end position drawing has exceeded 6 individual points. The TAC has a total of {{totalDrawnPoints}} points. If possible, reduce the number of points.",
88
+ "progress-intersection-above-6-points-message": "The start/end position of the intersected polygon has {{intersectingPolygonPointsTotal}} points, and the intersection of the drawn polygon with the FIR-boundary has exceeded 6 individual points. Check if the TAC in the preview corresponds to the intended area.",
89
+ "progress-radio-button-label-no-va-exp": "No volcanic ash expected",
90
+ "progress-radio-button-label-stationary": "Stationary",
91
+ "progress-radio-button-label-movement": "Movement",
92
+ "progress-radio-button-label-end-potision": "End position",
93
+ "progress-movement-direction-label": "Set direction",
94
+ "progress-movement-unit-label": "Unit",
95
+ "progress-movement-speed-label": "Step speed",
96
+ "progress-the-minimum-level-in-movement": "The minimum level in {{movementUnitType}} is {{movementUnit}}",
97
+ "progress-the-maxium-level-in-movement": "The maximum level in {{movementUnitType}} is {{movementUnit}}",
98
+ "progress-only-one-position-drawing": "Only one end position drawing is allowed",
99
+ at: "At",
100
+ select: "Select",
101
+ "observation-forecast-error": "Observation time cannot be in the future",
102
+ "start-position": "Start position",
103
+ between: "Between",
104
+ above: "Above",
105
+ change: "Change",
106
+ weakening: "Weakening",
107
+ "no-change": "No change",
108
+ intensifying: "Intensifying",
109
+ "issued-at": "Issued at",
110
+ "volcano-name": "Volcano name",
111
+ latitude: "Latitude",
112
+ longitude: "Longitude",
113
+ "tac-missing-data": "Missing data: no TAC can be generated",
114
+ "invalid-surface-wind-direction-message": "Direction must be rounded to the nearest {{value}} deg.",
115
+ "surface-wind-label": "wind direction",
116
+ "surface-wind-speed-label": "speed",
117
+ "surface-wind-helper-text": "Value in degrees",
118
+ "surface-wind-rule-min-max-message": "Direction should be between 10 and 360 deg.",
119
+ "surface-wind-minimum-wind-speed": "The minimum wind speed in {{windUnit}} is {{minWindSpeedValue}}",
120
+ "surface-wind-maximum-wind-speed": "The maximum wind speed in {{windUnit}} is {{maxWindSpeedValue}}",
121
+ "invalid-surface-visibility-till-750-steps-message": "A visibility below 750m must be rounded to the nearest {{value}}m",
122
+ "invalid-surface-visibility-from-750-steps-message": "A visibility above 750m must be rounded to the nearest {{value}}m",
123
+ set: "Set",
124
+ "levels-get-level-invalid-steps-for-fl-unit-message": "Levels must be rounded to the nearest {{value}}",
125
+ "levels-get-level-invalid-steps-for-ft-unit-message": "Levels must be rounded to the nearest {{value}}ft",
126
+ "levels-get-level-invalid-steps-for-m-unit-message": "Levels must be rounded to the nearest {{value}}m",
127
+ "levels-invalid-unit-message": "Level unit not defined",
128
+ "levels-invalid-level-unit-combination-message": "Invalid unit combination",
129
+ level: "Level",
130
+ "levels-the-minimum-level": "The minimum level in {{levelUnit}} is {{minLevelValue}}",
131
+ "levels-the-maximum-level": "The maximum level in {{levelUnit}} is {{maxLevelValue}}",
132
+ "levels-upper-level-label": "Upper level",
133
+ "unit-label": "Unit",
134
+ "levels-lower-level-label": "Lower level",
135
+ "levels-tops-label": "Tops",
136
+ progress: "Progress",
137
+ "surface-visibility": "Visibility",
138
+ "surface-visibility-cause": "Cause",
139
+ "surface-visibility-minimum-visibility": "The minimum visibility in meters is {{minimumVisibility}}",
140
+ "surface-visibility-maximum-visibility": "The maximum visibility in meters is {{maximumVisibility}}",
141
+ "surface-visibility-helper-text": "Value in meters",
142
+ "surface-visibility-between-time": "Forecast time should lie between the valid start and valid end time",
143
+ phenomenon: "Phenomenon"
23
144
  };
24
145
  var fi = {
25
- "sigmet-airmet": "sigmet"
146
+ "sigmet-airmet": "sigmet",
147
+ levels: "Tasot",
148
+ "not-published": "(Ei julkaistu)",
149
+ "valid-time": "Voimassa oleva aika",
150
+ "vulcanic-ash-description": "Käytä FIR:iä määrittääksesi suunnan johon vulkaaninen tuhkapilvi on liikkumassa",
151
+ "vulcanic-VA-SIGMET-text": "Peruuta VA SIGMET ilman VA MOV TO tietoja",
152
+ "vulcanic-cloud-moving-text": "Vulkaaninen tuhkapilvi on liikkumassa suuntaan: ",
153
+ unknown: "Ei tiedossa",
154
+ "create-new-product": "Luo uusi {{product}}",
155
+ discard: "HYLKÄÄ",
156
+ save: "Tallenna",
157
+ cancel: "Peruuta",
158
+ publish: "Julkaise",
159
+ back: "PALAA TAKAISIN",
160
+ draft: "LUONNOS",
161
+ "error-title": "Virhe konfiguraatiotiedostoa ladatessa",
162
+ "error-auth-login": "Tämän toiminnallisuuden käyttäminen vaatii tunnistautumista. Kirjaudu sisään jatkaaksesi",
163
+ "error-config": "Konfiguraatiota ladatessa on havaittu virhe",
164
+ "error-backend": "Tietoja haettaessa on havaittu virhe, yritä uudelleen",
165
+ "error-auth": "Tämän toiminnallisuuden käyttäminen vaatii tunnistautumista",
166
+ "saved-as-draft": "tallenna luonnoksena",
167
+ cancels: "Peruu",
168
+ close: "Sulje",
169
+ "discard-non-capitalized": "Hylkää",
170
+ "are-you-sure-you-want-to-discard": "Oletko varma, että haluat hylätä kyseisen {{product}}? Kaikki ilmoitetut tiedot menetetään",
171
+ "save-changes-made": "Haluatko tallentaa kaikki tehdyt muutokset?",
172
+ "publish-this-product": "Oletko varma, että haluat julkaista tämän {{product}}:n?",
173
+ "cancel-this-product": "Oletko varma, että haluat peruuttaa tämän {{product}}:n?",
174
+ "save-and-close": "Tallenna ja sulje",
175
+ "discard-and-close": "Hylkää ja sulje",
176
+ "drop-a-point-as": "Pudota piste kartalle ja käytä sitä {{type}} sijaintina ",
177
+ "draw-a-box-as": "Piirrä laatikko kartalle ja käytä sitä {{type}} sijaintina",
178
+ "draw-a-shape-as": "Piirrä muoto kartalle ja käytä sitä {{type}} sijaintina",
179
+ "set-a-fir-as": "Aseta FIR {{type}}:n sijaintina",
180
+ "remove-geometry": "Poista geometria",
181
+ "valid-until-time": "Voimassaoloajan päättymishetken on oltava voimassaoloajan alkuhetken jälkeen",
182
+ "discard-product": "Hylkää {{product}}",
183
+ "issue-time": "Julkaisuaika",
184
+ "type-title": "Tyyppi",
185
+ "phenomenon-title": "Mikä",
186
+ "observation-label": "Havainto",
187
+ "forecast-label": "Ennuste",
188
+ "valid-from-before-current-error": "Voimassaoloajan alkuhetki ei voi olla ennen nykyistä ajanhetkeä.",
189
+ "valid-from-time-error": "Voimassaoloajan alkuhetki ei voi olla enempää kuin {{hours}} nykyisen ajanhetken jälkeen.",
190
+ "date-and-time": "Päivämäärä ja aika",
191
+ "valid-from": "Alkuhetki",
192
+ "valid-until": "Päättymishetki",
193
+ "valid-until-time-error": "Voimassaoloajan loppuhetki ei voi olla enempää kuin {{hours}} voimassaoloajan alkuhetken jälkeen.",
194
+ "select-fir-title": "Missä",
195
+ "select-fir-label": "Valitse FIR",
196
+ "geometry-coodinates-empty-message": "Aloituspaikan piirros vaaditaan",
197
+ "geometry-no-intersection-message": "Aloituspaikan sijainnin on oltava ainakin osittain FIR:n sisäpuolella.",
198
+ "geometry-exit-draw-mode-message": "Paina ESC:iä poistuaksesi piirtotilasta",
199
+ "geometry-max-feature-points-message": "Piirretyn polygonin ja FIR-rajan leikkauspisteessä on yli 6 yksittäistä pistettä. Tarkita vastaako esikatselun TAC aiottua aluetta.",
200
+ "geometry-multi-intersections-message": "Piirretyllä polygonilla on useita leikkauspisteitä FIR-rajan kanssa. Piirrettyä polygonia käytetään TAC-koodin luomiseen",
201
+ "geometry-maximum-points-message": "Aloituspisteenä käytettävä piirros sallii maksimissaan {{maxPoints}} yksittäistä pistettä.",
202
+ "geometry-more-than-6-points-message": "Piirros jota käytetään sijainnin aloitukseen tai lopetukseen sisältää enemmän kuin sallitun määrän: 6 yksittäistä pistettä. TAC-viestissä on kaikenkaikkiaan {{totalDrawnPoints}} pistettä. Jos mahdollista, vähennä pisteiden määrää.",
203
+ "geometry-intersection-above-6-points-message": "Leikatun polygonin alku-/päätepisteessä on {{intersectingPolygonPointsTotal}} pistettä. Piirretyn polygonin ja FIR-rajan leikkauspiste on ylittänyt 6 yksittäistä pistettä. Tarkista vastaako esikatselun TAC aiottua aluetta.",
204
+ "geometry-only-one-start-position-drawing": "Vain yksi aloitusaluepiirros on sallittu.",
205
+ "progress-get-movement-step-valktmessage": "Nopeus tulisi pyöristää lähimpään {{value}}kt arvoon.",
206
+ "progress-get-movement-step-valkmhmessage": "Nopeus tulisi pyöristää lähimpään {{value}}kmh arvoon.",
207
+ "progress-coordinate-empty-message": "Lopetuspaikan piirtäminen on pakollista, kun valitset lopetuspaikan",
208
+ "progress-no-intersection-message": "Lopetuspaikan täytyy olla (osittain) FIR-alueen sisällä.",
209
+ "invalid-unit": "Virheellinen yksikkö",
210
+ "progress-maximumPointsMessage": "Lopetuspaikan piirtäminen sallii enintään {{maxPoints}} yksittäistä pistettä.",
211
+ "progress-more-than-6-points-message": "Aloitus-/lopetuspaikan piirroksessa on yli 6 yksittäistä pistettä. TAC:ssa on kaikenkaikkiaan {{totalDrawnPoints}} pistettä. Vähennä pisteiden määrää, jos mahdollista.",
212
+ "progress-intersection-above-6-points-message": "Leikatun polygonin aloitus-/lopetuspaikassa on {{intersectingPolygonPointsTotal}} pistettä. Piirretyn monikulmion leikkaus FIR-rajalla on ylittänyt 6 yksittäistä pistettä. Tarkista, vastaako esikatselun TAC aiottua aluetta.",
213
+ "progress-radio-button-label-no-va-exp": "Tulivuoren tuhkaa ei odotettavissa",
214
+ "progress-radio-button-label-stationary": "Liikkumaton",
215
+ "progress-radio-button-label-movement": "Liikkuva",
216
+ "progress-radio-button-label-end-potision": "Lopullinen sijainti",
217
+ "progress-movement-direction-label": "Aseta suunta",
218
+ "progress-movement-unit-label": "Yksikkö",
219
+ "progress-movement-speed-label": "Askeleen nopeus",
220
+ "progress-the-minimum-level-in-movement": "Pienin taso {{movementUnitType}}:ssa on {{movementUnit}}",
221
+ "progress-the-maxium-level-in-movement": "Suurin taso {{movementUnitType}}:ssa on {{movementUnit}}",
222
+ "progress-only-one-position-drawing": "Vain yksi lopetuspaikan piirros on sallittu",
223
+ at: "Ajanhetkessä",
224
+ select: "Valitse",
225
+ "observation-forecast-error": "Havainnon ajankohta ei voi olla tulevaisuudessa",
226
+ "start-position": "Alkusijainti",
227
+ between: "Välissä",
228
+ above: "Yläpuolella",
229
+ change: "Muutos",
230
+ weakening: "Heikentyvä",
231
+ "no-change": "Ei muutosta",
232
+ intensifying: "Vahvistuva",
233
+ "issued-at": "Annettu klo:",
234
+ "volcano-name": "Tulivuoren nimi",
235
+ latitude: "Leveysaste",
236
+ longitude: "Pituusaste",
237
+ "tac-missing-data": "Tarvittavia tietoja puuttu, TAC:ia ei voida generoida",
238
+ "invalid-surface-wind-direction-message": "Suunta tulee pyöristää lähimpään {{value}} asteeseen.",
239
+ "surface-wind-label": "tuulen suunta",
240
+ "surface-wind-speed-label": "nopeus",
241
+ "surface-wind-helper-text": "Arvo asteina",
242
+ "surface-wind-rule-min-max-message": "Suunnan on oltava 10 ja 360 asteen välissä.",
243
+ "surface-wind-minimum-wind-speed": "Minimituulennopeus käyttäen yksikköä {{windUnit}} on {{minWindSpeedValue}}",
244
+ "surface-wind-maximum-wind-speed": "Maksimituulennopeus käyttäen yksikköä {{windUnit}} on {{maxWindSpeedValue}}",
245
+ "invalid-surface-visibility-till-750-steps-message": "Alle 750m näkyvyys tulee pyöristää lähimpään {{value}}m arvoon.",
246
+ "invalid-surface-visibility-from-750-steps-message": "Yli 750m näkyvyys tulee pyöristää lähimpään {{value}}m arvoon.",
247
+ set: "Aseta",
248
+ "levels-get-level-invalid-steps-for-fl-unit-message": "Tasot tulee pyöristää lähimpään {{value}} arvoon.",
249
+ "levels-get-level-invalid-steps-for-ft-unit-message": "Tasot tulee pyöristää lähimpään {{value}}ft arvoon.",
250
+ "levels-get-level-invalid-steps-for-m-unit-message": "Tasot tulee pyöristää lähimpään {{value}}m arvoon",
251
+ "levels-invalid-unit-message": "Tason yksikkö ei ole määritelty",
252
+ "levels-invalid-level-unit-combination-message": "Virheellinen yhdistelmä yksiköitä",
253
+ level: "Taso",
254
+ "levels-the-maximum-level": "Tason maksimiarvo käyttäen yksikköä {{levelUnit}} on {{maxLevelValue}}",
255
+ "levels-the-minimum-level": "Tason minimiarvo käyttäen yksiköä {{levelUnit}} on {{minLevelValue}} ",
256
+ "levels-upper-level-label": "Ylempi taso",
257
+ "unit-label": "Yksikkö",
258
+ "levels-lower-level-label": "Alempi taso",
259
+ "levels-tops-label": "Ylittää",
260
+ progress: "Edistyminen",
261
+ "surface-visibility": "Näkyvyys",
262
+ "surface-visibility-cause": "Aiheuttaja",
263
+ "surface-visibility-minimum-visibility": "Miniminäkyvyys metreinä: {{minimumVisibility}}",
264
+ "surface-visibility-maximum-visibility": "Maksiminäkyvyys metreinä: {{maximumVisibility}}",
265
+ "surface-visibility-helper-text": "Arvo metreinä",
266
+ "surface-visibility-between-time": "Ennusteajan tulee olla voimassa olevan alkamis- ja päättymisajan välissä",
267
+ phenomenon: "sääilmiö"
26
268
  };
27
269
  var no = {
28
- "sigmet-airmet": "sigmet"
270
+ "sigmet-airmet": "sigmet",
271
+ levels: "Nivå",
272
+ "not-published": "(Ikke publisert)",
273
+ "valid-time": "Gyldig tid",
274
+ "vulcanic-ash-description": "Bruk FIR til å indikere retningen den vulkanske asken går mot",
275
+ "vulcanic-VA-SIGMET-text": "ikke oversatt",
276
+ "vulcanic-cloud-moving-text": "Vulkansk askesky går mot",
277
+ unknown: "Ukjent",
278
+ "create-new-product": "Lage et nytt {{ product }}",
279
+ discard: "FORKAST",
280
+ save: "Lagre",
281
+ cancel: "Avbryt",
282
+ publish: "Publiser",
283
+ back: "TILBAKE",
284
+ draft: "KLADD",
285
+ "error-title": "Noe gikk galt med innlasting av konfigurasjonfil",
286
+ "error-auth-login": "Denne delen er passordbeskyttet. Vennligst logg inn.",
287
+ "error-config": "En feil har oppstått ved innlasting av konfigurasjonfil",
288
+ "error-backend": "En feil har oppstått ved nedlasting av listen, vennligst prøv igjen.",
289
+ "error-auth": "Denne delen er passordbeskyttet.",
290
+ "saved-as-draft": "Lagre som kladd",
291
+ cancels: "Avbryter",
292
+ close: "Lukk",
293
+ "discard-non-capitalized": "Forkast",
294
+ "are-you-sure-you-want-to-discard": "Er du sikker på at du vil forkaste dette {{product}}?",
295
+ "save-changes-made": "Vil du lagre endringene dine?",
296
+ "publish-this-product": "Er du sikker på at du vil endre dette {{product}}?",
297
+ "cancel-this-product": "Er du sikker på at du vil avbryte dette {{product}}?",
298
+ "save-and-close": "Lagre og lukk",
299
+ "discard-and-close": "Forkast og lukk",
300
+ "drop-a-point-as": "Fjern et punkt som {{type}}posisjon",
301
+ "draw-a-box-as": "Tegn en boks som {{type}}posisjon",
302
+ "draw-a-shape-as": "Tegn en shape som {{type}}posisjon",
303
+ "set-a-fir-as": "Sett FIR som {{type}}posisjon",
304
+ "remove-geometry": "Fjern geometry",
305
+ "valid-until-time": "Gyldig til tid må være etter Gyldig fra tid",
306
+ "discard-product": "Forkast {{product}}",
307
+ "issue-time": "Utstedt tid",
308
+ "type-title": "Type",
309
+ "phenomenon-title": "Hva",
310
+ "observation-label": "Observert",
311
+ "forecast-label": "Varsel",
312
+ "valid-from-before-current-error": "Gyldig fra tid må være før Gyldig til tid",
313
+ "valid-from-time-error": "Gyldig fra tid kan ikke være mer enn {{hours}} timer etter nå tidspunkt",
314
+ "date-and-time": "Dato og tid",
315
+ "valid-from": "Gyldig fra",
316
+ "valid-until": "Gyldig til",
317
+ "valid-until-time-error": "Gyldig til tid kan ikke være mer enn {{hours}} timer etter Gyldig fra tid",
318
+ "select-fir-title": "Hvor",
319
+ "select-fir-label": "Velg FIR",
320
+ "geometry-coodinates-empty-message": "En startposisjon er påkrevd",
321
+ "geometry-no-intersection-message": "Startposisjonen må være (delvis) innenfor FIR'en",
322
+ "geometry-exit-draw-mode-message": "Trykk på ESC for å avslutte tegnemodus",
323
+ "geometry-max-feature-points-message": "Skjeringspunktene mellom det tegnede polygonet og FIR-grensen har mer enn 6 individuelle punkt. Sjekk om TAC'en i forhåndsvining korresponderer med det utvidetet området.",
324
+ "geometry-multi-intersections-message": "Det tegnede polygonet har mange skjæringspunkt med FIR-grensen. Det tegnede polygonet vil bli brukt i TAC-koden.",
325
+ "geometry-maximum-points-message": "Startposisjonen tillater et maksimum av {{maxPoints}} individuelle punkt",
326
+ "geometry-more-than-6-points-message": "Start-/sluttposisjonen har mer enn 6 individuelle punkt. TAC'en har totalt {{totalDrawnPoints}} punkt. Reduser antall punkt dersom det er mulig.",
327
+ "geometry-intersection-above-6-points-message": "Start-/sluttposisjonen til det kryssede polygonet har {{intersectingPolygonPointsTotal}} punkt, og skjæringspunktet mellom det tegnede polygonet og FIR-grensen har mer enn 6 individuelle punkt. Sjekk om forhåndsvisningen av TAC'en korresponderer med det tiltenkte området.",
328
+ "geometry-only-one-start-position-drawing": "Bare én startposisjonstegning er tillatt",
329
+ "progress-get-movement-step-valktmessage": "Hastighet bør avrundes til nærmeste {{value}}kt",
330
+ "progress-get-movement-step-valkmhmessage": "Hastighet bør avrundes til nærmeste {{value}}km/t",
331
+ "progress-coordinate-empty-message": "En endeposisjonstegning kreves når en har valgt Sluttposisjon",
332
+ "progress-no-intersection-message": "Sluttposisjonen må være (delvis) inne i FIR'en",
333
+ "invalid-unit": "Ugyldig enhet",
334
+ "progress-maximumPointsMessage": "Sluttposisjonstegningen tillater maks {{maxPoints}} individuelle punkt.",
335
+ "progress-more-than-6-points-message": "Start-/sluttposisjonen har mer enn 6 individuelle punkt. TAC'en har totalt {{totalDrawnPoints}} punkt. Reduser antall punkt dersom det er mulig.",
336
+ "progress-intersection-above-6-points-message": "Start-/sluttposisjonen til det kryssede polygonet har {{intersectingPolygonPointsTotal}} punkt, og skjæringspunktet mellom det tegnede polygonet og FIR-grensen har mer enn 6 individuelle punkt. Sjekk om forhåndsvisningen av TAC'en korresponderer med det tiltenkte området.",
337
+ "progress-radio-button-label-no-va-exp": "Det er ikke ventet noe vulkansk aske",
338
+ "progress-radio-button-label-stationary": "Stasjonær",
339
+ "progress-radio-button-label-movement": "Bevegelse",
340
+ "progress-radio-button-label-end-potision": "Sluttposisjon",
341
+ "progress-movement-direction-label": "Sett retning",
342
+ "progress-movement-unit-label": "Enhet",
343
+ "progress-movement-speed-label": "Trinnhastighet",
344
+ "progress-the-minimum-level-in-movement": "Minstenivået i {{movementUnitType}} er {{movementUnit}}",
345
+ "progress-the-maxium-level-in-movement": "Det største nivået i {{movementUnitType}} er {{movementUnit}}",
346
+ "progress-only-one-position-drawing": "Det er bare tillatt med en sluttposisjon",
347
+ at: "Ved",
348
+ select: "Velg",
349
+ "observation-forecast-error": "Observasjonstidspunkt kan ikke være i fremtiden",
350
+ "start-position": "Startposisjon",
351
+ between: "Mellom",
352
+ above: "Over",
353
+ change: "Endre",
354
+ weakening: "Svekkelse",
355
+ "no-change": "Ingen endring",
356
+ intensifying: "Intensifisering",
357
+ "issued-at": "Utstedt tid",
358
+ "volcano-name": "Navn på vulkan",
359
+ latitude: "Breddegrad",
360
+ longitude: "Lengdegrad",
361
+ "tac-missing-data": "Manglende data: ingen TAC kan bli laget",
362
+ "invalid-surface-wind-direction-message": "Retning må være avrundet til nærmeste {{value}} grad.",
363
+ "surface-wind-label": "vindretning",
364
+ "surface-wind-speed-label": "hastighet",
365
+ "surface-wind-helper-text": "Verdi i grader",
366
+ "surface-wind-rule-min-max-message": "Retning skal være mellom 10 og 360 grader.",
367
+ "surface-wind-minimum-wind-speed": "Minimum vindhastighet i {{windUnit}} er {{minWindSpeedValue}}",
368
+ "surface-wind-maximum-wind-speed": "Maksimal vindhastighet i {{windUnit}} er {{minWindSpeedValue}}",
369
+ "invalid-surface-visibility-till-750-steps-message": "Sikt under 750m må avrundes til nærmeste {{value}}m",
370
+ "invalid-surface-visibility-from-750-steps-message": "Sikt over 750m må avrundes til nærmeste {{value}}m",
371
+ set: "Sett",
372
+ "levels-get-level-invalid-steps-for-fl-unit-message": "Nivå må avrundes til nærmeste {{value}}",
373
+ "levels-get-level-invalid-steps-for-ft-unit-message": "Nivå må avrundes til nærmeste {{value}}ft",
374
+ "levels-get-level-invalid-steps-for-m-unit-message": "Nivå må avrundes til nærmeste {{value}}m",
375
+ "levels-invalid-unit-message": "Nivåenhet er ikke definert",
376
+ "levels-invalid-level-unit-combination-message": "Ugylid kombinasjon av enhet",
377
+ level: "Nivå",
378
+ "levels-the-minimum-level": "Minste nivå i {{levelUnit}} er {{minLevelValue}}",
379
+ "levels-the-maximum-level": "Maksimal nivå i {{levelUnit}} er {{minLevelValue}}",
380
+ "levels-upper-level-label": "Øvre nivå",
381
+ "unit-label": "Enhet",
382
+ "levels-lower-level-label": "Nedre nivå",
383
+ "levels-tops-label": "Topper",
384
+ progress: "Framgang",
385
+ "surface-visibility": "Sikt",
386
+ "surface-visibility-cause": "Grunn",
387
+ "surface-visibility-minimum-visibility": "Minimal sikt i meter er {{minimumVisibility}}",
388
+ "surface-visibility-maximum-visibility": "Maksimal sikt i meter er {{minimumVisibility}}",
389
+ "surface-visibility-helper-text": "Verdi i meter",
390
+ phenomenon: "Fenomen"
29
391
  };
30
392
  var nl = {
31
- "sigmet-airmet": "sigmet"
393
+ "sigmet-airmet": "sigmet",
394
+ levels: "Niveaus",
395
+ "not-published": "(Niet gepubliceerd)",
396
+ "valid-time": "Geldige tijd",
397
+ "vulcanic-ash-description": "Gebruik de FIR om aan te geven in welke richting de vulkanische as beweegt",
398
+ "vulcanic-VA-SIGMET-text": "Annuleer VA SIGMET zonder VA MOV TO-informatie",
399
+ "vulcanic-cloud-moving-text": "Vulkanische aswolk beweegt zich in de richting van",
400
+ unknown: "Onbekend",
401
+ "create-new-product": "Maak nieuwe {{ product }}",
402
+ discard: "WEGGOOIEN",
403
+ save: "Bewaar",
404
+ cancel: "Annuleer",
405
+ publish: "Publiceer",
406
+ back: "TERUG",
407
+ draft: "CONCEPT",
408
+ "error-title": "Er is iets misgegaan bij het laden van het configuratiebestand",
409
+ "error-auth-login": "Deze functie wordt beschermd door authenticatie. Log in om verder te gaan",
410
+ "error-config": "Er is een fout opgetreden tijdens het laden van de configuratie",
411
+ "error-backend": "Er is een fout opgetreden bij het ophalen van de lijst. Probeer het opnieuw",
412
+ "error-auth": "Deze functie wordt beschermd door authenticatie",
413
+ "saved-as-draft": "opgeslagen als concept",
414
+ cancels: "Annuleert",
415
+ close: "Sluit",
416
+ "discard-non-capitalized": "Weggooien",
417
+ "are-you-sure-you-want-to-discard": "Weet je zeker dat je dit {{product}} wilt weggooien? De eigenschappen ervan zullen verloren gaan",
418
+ "save-changes-made": "Wil je de aangebrachte wijzigingen opslaan?",
419
+ "publish-this-product": "Weet je zeker dat je dit {{product}} wilt publiceren?",
420
+ "cancel-this-product": "Weet je zeker dat je dit {{product}} wilt annuleren?",
421
+ "save-and-close": "Opslaan en sluiten",
422
+ "discard-and-close": "Gooi weg en sluit",
423
+ "drop-a-point-as": "Zet punt neer als {{type}} positie",
424
+ "draw-a-box-as": "Teken een vierkant als {{type}} positie",
425
+ "draw-a-shape-as": "Teken een vorm als {{type}} positie",
426
+ "set-a-fir-as": "Zet FIR als {{type}} positie`",
427
+ "remove-geometry": "Verwijder geometrie",
428
+ "valid-until-time": "Eind tijd moet na tijd vanaf zijn",
429
+ "discard-product": "Gooi {{product}} weg",
430
+ "issue-time": "Uitgiftetijd",
431
+ "type-title": "Type",
432
+ "phenomenon-title": "Wat",
433
+ "observation-label": "Opgemerkt",
434
+ "forecast-label": "Voorspelling",
435
+ "valid-from-before-current-error": "Vanaf tijd kan niet voor huidige tijd zijn",
436
+ "valid-from-time-error": "Geldig vanaf tijd kan maximaal {{hours}} uur na huidige tijd zijn",
437
+ "date-and-time": "Datum en tijd",
438
+ "valid-from": "Geldig vanaf",
439
+ "valid-until": "Geldig tot",
440
+ "valid-until-time-error": "Geldig tot tijd mag maximaal {{hours}} uur na Geldig vanaf tijd zijn",
441
+ "select-fir-title": "Waar",
442
+ "select-fir-label": "Selecteer FIR",
443
+ "geometry-coodinates-empty-message": "Een startpositietekening is vereist",
444
+ "geometry-no-intersection-message": "De startpositie moet (gedeeltelijk) binnen de FIR liggen",
445
+ "geometry-exit-draw-mode-message": "Druk op ESC om de tekenmodus te verlaten",
446
+ "geometry-max-feature-points-message": "Het snijpunt van de getekende veelhoek met de FIR-grens heeft meer dan 6 individuele punten. Controleer of de TAC in het voorbeeld overeenkomt met het beoogde gebied.",
447
+ "geometry-multi-intersections-message": "De getekende veelhoek heeft meerdere snijpunten met de FIR-grens. De getekende polygoon wordt gebruikt voor de TAC-code.",
448
+ "geometry-maximum-points-message": "Bij het tekenen van de startpositie zijn maximaal {{maxPoints}} individuele punten mogelijk",
449
+ "geometry-more-than-6-points-message": "De start-/eindpositietekening heeft 6 individuele punten overschreden. De TAC heeft een totaal van {{totalDrawnPoints}} punten. Verminder indien mogelijk het aantal punten.",
450
+ "geometry-intersection-above-6-points-message": "De begin-/eindpositie van de doorgesneden polygoon heeft {{intersectingPolygonPointsTotal}} punten, en het snijpunt van de getekende polygoon met de FIR-grens heeft 6 individuele punten overschreden. Controleer of de TAC in de preview overeenkomt met het beoogde gebied.",
451
+ "geometry-only-one-start-position-drawing": "Er is slechts één startpositietekening toegestaan",
452
+ "progress-get-movement-step-valktmessage": "De snelheid moet worden afgerond op de dichtstbijzijnde {{value}}kt",
453
+ "progress-get-movement-step-valkmhmessage": "De snelheid moet worden afgerond op de dichtstbijzijnde {{value}}km/u",
454
+ "progress-coordinate-empty-message": "Bij het selecteren van Eindpositie is een eindpositietekening vereist",
455
+ "progress-no-intersection-message": "De eindpositie moet (gedeeltelijk) binnen de FIR liggen",
456
+ "invalid-unit": "Ongeldige eenheid",
457
+ "progress-maximumPointsMessage": "De eindpositietekening staat een maximum van {{maxPoints}} individuele punten toe",
458
+ "progress-more-than-6-points-message": "De start-/eindpositietekening heeft 6 individuele punten overschreden. De TAC heeft een totaal van {{totalDrawnPoints}} punten. Verminder indien mogelijk het aantal punten.",
459
+ "progress-intersection-above-6-points-message": "De start-/eindpositietekening heeft 6 individuele punten bepaald. De TAC heeft een totaal van {{totalDrawnPoints}} punten. Verminder mogelijk indien het aantal punten.",
460
+ "progress-radio-button-label-no-va-exp": "Geen vulkanische as verwacht",
461
+ "progress-radio-button-label-stationary": "Stationair",
462
+ "progress-radio-button-label-movement": "Beweging",
463
+ "progress-radio-button-label-end-potision": "Eind positie",
464
+ "progress-movement-direction-label": "Richting instellen",
465
+ "progress-movement-unit-label": "Eenheid",
466
+ "progress-movement-speed-label": "Stap snelheid",
467
+ "progress-the-minimum-level-in-movement": "Het minimumniveau in {{movementUnitType}} is {{movementUnit}}",
468
+ "progress-the-maxium-level-in-movement": "Het maximumniveau in {{movementUnitType}} is {{movementUnit}}",
469
+ "progress-only-one-position-drawing": "Er is slechts één eindpositietekening toegestaan",
470
+ at: "Bij",
471
+ select: "Selecteer",
472
+ "observation-forecast-error": "Observatietijd kan niet in de toekomst liggen",
473
+ "start-position": "Start positie",
474
+ between: "Tussen",
475
+ above: "Boven",
476
+ change: "Verandering",
477
+ weakening: "Verzwakking",
478
+ "no-change": "Geen verandering",
479
+ intensifying: "Intensivering",
480
+ "issued-at": "Uitgegeven op",
481
+ "volcano-name": "Naam vulkaan",
482
+ latitude: "Breedtegraad",
483
+ longitude: "Lengtegraad",
484
+ "tac-missing-data": "Ontbrekende gegevens: er kan geen TAC worden gegenereerd",
485
+ "invalid-surface-wind-direction-message": "De richting moet worden afgerond op de dichtstbijzijnde {{value}} graden.",
486
+ "surface-wind-label": "windrichting",
487
+ "surface-wind-speed-label": "snelheid",
488
+ "surface-wind-helper-text": "Waarde in graden",
489
+ "surface-wind-rule-min-max-message": "De richting moet tussen 10 en 360 graden liggen.",
490
+ "surface-wind-minimum-wind-speed": "De minimale windsnelheid in {{windUnit}} is {{minWindSpeedValue}}",
491
+ "surface-wind-maximum-wind-speed": "De maximale windsnelheid in {{windUnit}} is {{maxWindSpeedValue}}",
492
+ "invalid-surface-visibility-till-750-steps-message": "Een zicht onder de 750 meter moet worden afgerond op de dichtstbijzijnde {{value}} meter",
493
+ "invalid-surface-visibility-from-750-steps-message": "Een zicht boven 750 meter moet worden afgerond op de dichtstbijzijnde {{value}} meter",
494
+ set: "Instellen",
495
+ "levels-get-level-invalid-steps-for-fl-unit-message": "Niveaus moeten worden afgerond op de dichtstbijzijnde {{value}}",
496
+ "levels-get-level-invalid-steps-for-ft-unit-message": "Niveaus moeten worden afgerond op de dichtstbijzijnde {{value}}ft",
497
+ "levels-get-level-invalid-steps-for-m-unit-message": "Niveaus moeten worden afgerond op de dichtstbijzijnde {{value}}m",
498
+ "levels-invalid-unit-message": "Niveau-eenheid niet gedefinieerd",
499
+ "levels-invalid-level-unit-combination-message": "Ongeldige eenheidscombinatie",
500
+ level: "Niveau",
501
+ "levels-the-minimum-level": "Het minimumniveau in {{levelUnit}} is {{minLevelValue}}",
502
+ "levels-the-maximum-level": "Het maximumniveau in {{levelUnit}} is {{maxLevelValue}}",
503
+ "levels-upper-level-label": "Bovenste niveau",
504
+ "unit-label": "Eenheid",
505
+ "levels-lower-level-label": "Laagste niveau",
506
+ "levels-tops-label": "Bovenkant",
507
+ progress: "Voortgang",
508
+ "surface-visibility": "Zichtbaarheid",
509
+ "surface-visibility-cause": "Oorzaak",
510
+ "surface-visibility-minimum-visibility": "De minimale zichtbaarheid in meters is {{minimumVisibility}}",
511
+ "surface-visibility-maximum-visibility": "De maximale zichtbaarheid in meters is {{maximumVisibility}}",
512
+ "surface-visibility-helper-text": "Waarde in meters",
513
+ "surface-visibility-between-time": "De prognosetijd moet tussen de geldige start- en eindtijd liggen",
514
+ phenomenon: "Fenomeen"
32
515
  };
33
516
  var sigmetAirmetTranslations = {
34
517
  en: en,
@@ -2069,10 +2552,20 @@ const useShortTestHelpers = () => {
2069
2552
  };
2070
2553
  };
2071
2554
 
2555
+ const SA_NAMESPACE = 'sigmetairmet';
2556
+ const ns = [SA_NAMESPACE, FORM_FIELDS_NAMESPACE];
2557
+ const translateKeyOutsideComponents = (key, params = undefined) => i18n.t(key, Object.assign({
2558
+ ns
2559
+ }, params));
2560
+ const useSigmetAirmetTranslation = () => useTranslation(ns);
2561
+
2072
2562
  const Change = ({
2073
2563
  isDisabled,
2074
2564
  isReadOnly
2075
2565
  }) => {
2566
+ const {
2567
+ t
2568
+ } = useSigmetAirmetTranslation();
2076
2569
  const {
2077
2570
  isRequired: isRequiredField
2078
2571
  } = useDraftFormHelpers();
@@ -2082,7 +2575,7 @@ const Change = ({
2082
2575
  const isRequired = value => isShortTest() || isRequiredField(value);
2083
2576
  const fieldsDisabled = isDisabled || isShortTest();
2084
2577
  return jsx(ProductFormFieldLayout, Object.assign({
2085
- title: "Change",
2578
+ title: t('change'),
2086
2579
  sx: styles$2.containerItem
2087
2580
  }, {
2088
2581
  children: jsx(Grid, Object.assign({
@@ -2101,17 +2594,17 @@ const Change = ({
2101
2594
  }, {
2102
2595
  children: [jsx(RadioButtonAndLabel, {
2103
2596
  value: "WKN",
2104
- label: "Weakening",
2597
+ label: t('weakening'),
2105
2598
  disabled: fieldsDisabled,
2106
2599
  "data-testid": "change-WKN"
2107
2600
  }), jsx(RadioButtonAndLabel, {
2108
2601
  value: "NC",
2109
- label: "No change",
2602
+ label: t('no-change'),
2110
2603
  disabled: fieldsDisabled,
2111
2604
  "data-testid": "change-NC"
2112
2605
  }), jsx(RadioButtonAndLabel, {
2113
2606
  value: "INTSF",
2114
- label: "Intensifying",
2607
+ label: t('intensifying'),
2115
2608
  disabled: fieldsDisabled,
2116
2609
  "data-testid": "change-INTSF"
2117
2610
  })]
@@ -2621,12 +3114,12 @@ const getDialogtitle = (product, productType) => {
2621
3114
  }
2622
3115
  if (!isInstanceOfCancelSigmetOrAirmet(product)) {
2623
3116
  const phenomenon = productType === 'sigmet' ? SigmetPhenomena[product.phenomenon] : AirmetPhenomena[product.phenomenon];
2624
- return `${productName} ${phenomenon} - ${product.status === 'DRAFT' ? 'saved as draft' : ProductStatusDescription[product.status]}`;
3117
+ return `${productName} ${phenomenon} - ${product.status === 'DRAFT' ? translateKeyOutsideComponents('saved-as-draft') : ProductStatusDescription[product.status]}`;
2625
3118
  }
2626
3119
  if (isInstanceOfCancelSigmet(product)) {
2627
- return `${productName} Cancels ${product.cancelsSigmetSequenceId}`;
3120
+ return `${productName} ${translateKeyOutsideComponents('cancels')} ${product.cancelsSigmetSequenceId}`;
2628
3121
  }
2629
- return `${productName} Cancels ${product.cancelsAirmetSequenceId}`;
3122
+ return `${productName} ${translateKeyOutsideComponents('cancels')} ${product.cancelsAirmetSequenceId}`;
2630
3123
  };
2631
3124
  const getProductFormMode = (canBeOptions, productListItem) => {
2632
3125
  if (productListItem === null) {
@@ -2651,17 +3144,17 @@ const getProductFormLifecycleButtons = ({
2651
3144
  const hasPublishButton = canBe.includes('PUBLISHED');
2652
3145
  const onPublish = () => onButtonPress('PUBLISHED');
2653
3146
  const mobileMenuItems = [...(hasDiscardButton ? [{
2654
- text: 'Discard',
3147
+ text: translateKeyOutsideComponents('discard'),
2655
3148
  action: onDiscard
2656
3149
  }] : []), ...(hasSaveButton ? [{
2657
- text: 'Save',
3150
+ text: translateKeyOutsideComponents('save'),
2658
3151
  action: onSave,
2659
3152
  isDisabled: _areActionsDisabled
2660
3153
  }] : []), ...(hasCancelButton ? [{
2661
- text: 'Cancel',
3154
+ text: translateKeyOutsideComponents('cancel'),
2662
3155
  action: onCancel
2663
3156
  }] : []), ...(hasPublishButton ? [{
2664
- text: 'Publish',
3157
+ text: translateKeyOutsideComponents('publish'),
2665
3158
  action: onPublish,
2666
3159
  isDisabled: _areActionsDisabled
2667
3160
  }] : [])];
@@ -2686,7 +3179,7 @@ const getProductFormLifecycleButtons = ({
2686
3179
  sx: buttonStyle,
2687
3180
  "data-testid": "productform-dialog-discard"
2688
3181
  }, {
2689
- children: "DISCARD"
3182
+ children: translateKeyOutsideComponents('discard')
2690
3183
  })), hasSaveButton && jsx(Button, Object.assign({
2691
3184
  variant: "tertiary",
2692
3185
  onClick: onSave,
@@ -2694,14 +3187,14 @@ const getProductFormLifecycleButtons = ({
2694
3187
  "data-testid": "productform-dialog-draft",
2695
3188
  disabled: _areActionsDisabled
2696
3189
  }, {
2697
- children: "Save"
3190
+ children: translateKeyOutsideComponents('save')
2698
3191
  })), hasCancelButton && jsx(Button, Object.assign({
2699
3192
  variant: "tertiary",
2700
3193
  onClick: onCancel,
2701
3194
  sx: buttonStyle,
2702
3195
  "data-testid": "productform-dialog-cancel"
2703
3196
  }, {
2704
- children: "Cancel"
3197
+ children: translateKeyOutsideComponents('cancel')
2705
3198
  })), hasPublishButton && jsx(Button, Object.assign({
2706
3199
  variant: "primary",
2707
3200
  onClick: onPublish,
@@ -2709,7 +3202,7 @@ const getProductFormLifecycleButtons = ({
2709
3202
  "data-testid": "productform-dialog-publish",
2710
3203
  disabled: _areActionsDisabled
2711
3204
  }, {
2712
- children: "Publish"
3205
+ children: translateKeyOutsideComponents('publish')
2713
3206
  }))]
2714
3207
  })), jsx(Box, Object.assign({
2715
3208
  display: {
@@ -2779,46 +3272,54 @@ const createAirmetPostParameter = (airmetToPost, newStatus, previousUuid) => {
2779
3272
  const getConfirmationDialogTitle = (action, productType) => {
2780
3273
  const product = productType.toUpperCase();
2781
3274
  if (action === 'CLOSED') {
2782
- return `Close ${product}`;
3275
+ return `${translateKeyOutsideComponents('close')} ${product}`;
2783
3276
  }
2784
3277
  if (action === 'DISCARDED') {
2785
- return `Discard ${product}`;
3278
+ return `${translateKeyOutsideComponents('discard-non-capitalized')} ${product}`;
2786
3279
  }
2787
3280
  if (action === 'PUBLISHED') {
2788
- return 'Publish';
3281
+ return translateKeyOutsideComponents('publish');
2789
3282
  }
2790
- return `Cancel ${product}`;
3283
+ return `${translateKeyOutsideComponents('cancel')} ${product}`;
2791
3284
  };
2792
3285
  const getConfirmationDialogContent = (action, productType) => {
2793
3286
  const product = productType.toUpperCase();
2794
3287
  if (action === 'DISCARDED') {
2795
- return `Are you sure you would like to discard this ${product}? Its properties will be lost`;
3288
+ return translateKeyOutsideComponents('are-you-sure-you-want-to-discard', {
3289
+ product
3290
+ });
2796
3291
  }
2797
3292
  if (action === 'CLOSED') {
2798
- return 'Do you want to save any changes made?';
3293
+ return translateKeyOutsideComponents('save-changes-made');
2799
3294
  }
2800
3295
  if (action === 'PUBLISHED') {
2801
- return `Are you sure you want to publish this ${product}?`;
3296
+ return translateKeyOutsideComponents('publish-this-product', {
3297
+ product
3298
+ });
2802
3299
  }
2803
- return `Are you sure you want to cancel this ${product}?`;
3300
+ return translateKeyOutsideComponents('cancel-this-product', {
3301
+ product
3302
+ });
2804
3303
  };
2805
3304
  const getConfirmationDialogButtonLabel = (action, productType) => {
2806
3305
  const product = productType.toUpperCase();
2807
3306
  switch (action) {
2808
3307
  case 'DISCARDED':
2809
- return `Discard ${product}`;
3308
+ return `${translateKeyOutsideComponents('discard-product', {
3309
+ product
3310
+ })}`;
2810
3311
  case 'PUBLISHED':
2811
- return 'Publish';
3312
+ return translateKeyOutsideComponents('publish');
2812
3313
  case 'CANCELLED':
2813
- return 'Cancel';
3314
+ return translateKeyOutsideComponents('cancel');
2814
3315
  default:
2815
- return 'Save and close';
3316
+ return translateKeyOutsideComponents('save-and-close');
2816
3317
  }
2817
3318
  };
2818
3319
  const getConfirmationDialogCancelLabel = action => {
2819
3320
  switch (action) {
2820
3321
  case 'CLOSED':
2821
- return 'Discard and close';
3322
+ return translateKeyOutsideComponents('discard-and-close');
2822
3323
  default:
2823
3324
  return undefined;
2824
3325
  }
@@ -2830,7 +3331,7 @@ const getProductIssueDate = (initialProduct, initialCancelProduct) => {
2830
3331
  if (initialCancelProduct !== null && initialCancelProduct.issueDate) {
2831
3332
  return `${dateUtils.dateToString(dateUtils.utc(initialCancelProduct.issueDate), dateUtils.DATE_FORMAT_DATEPICKER)} UTC`;
2832
3333
  }
2833
- return '(Not published)';
3334
+ return translateKeyOutsideComponents('not-published');
2834
3335
  };
2835
3336
  // Provide a cross section of the units from the config and the units as allowed by the type definition
2836
3337
  // Units from the config which are not in the type definition should be ignored
@@ -2867,7 +3368,7 @@ const getFir = (productConfig, firName) => {
2867
3368
  const isFir = geojson => {
2868
3369
  return geojson && geojson.features && geojson.features.length > 0 && geojson.features[0].properties['selectionType'] === 'fir';
2869
3370
  };
2870
- const getFieldLabel = (title, isDisabled, action = 'Select') => isDisabled ? title : `${action} ${title.toLowerCase()}`;
3371
+ const getFieldLabel = (title, isDisabled, action = translateKeyOutsideComponents('select')) => isDisabled ? title : `${action} ${title.toLowerCase()}`;
2871
3372
  const getBaseLayers = productConfig => {
2872
3373
  var _a, _b;
2873
3374
  return ((_b = (_a = productConfig.mapPreset) === null || _a === void 0 ? void 0 : _a.layers) === null || _b === void 0 ? void 0 : _b.filter(layer => layer.layerType === LayerType.baseLayer || layer.layerType === LayerType.overLayer)) || [];
@@ -2904,24 +3405,32 @@ const firSelectionType = 'fir';
2904
3405
  const getDrawTools = (type, firShape) => {
2905
3406
  const defaultStyleProperties = type === StartOrEndDrawing.start ? featurePropsStart : featurePropsEnd;
2906
3407
  return [Object.assign(Object.assign({}, defaultPoint), {
2907
- title: `Drop a point as ${type} position`,
3408
+ title: translateKeyOutsideComponents('drop-a-point-as', {
3409
+ type
3410
+ }),
2908
3411
  shape: addGeoJSONProperties(defaultPoint.shape, defaultStyleProperties)
2909
3412
  }), Object.assign(Object.assign({}, defaultBox), {
2910
- title: `Draw a box as ${type} position`,
3413
+ title: translateKeyOutsideComponents('draw-a-box-as', {
3414
+ type
3415
+ }),
2911
3416
  shape: addGeoJSONProperties(defaultBox.shape, defaultStyleProperties)
2912
3417
  }), Object.assign(Object.assign({}, defaultPolygon), {
2913
- title: `Draw a shape as ${type} position`,
3418
+ title: translateKeyOutsideComponents('draw-a-shape-as', {
3419
+ type
3420
+ }),
2914
3421
  shape: addGeoJSONProperties(defaultPolygon.shape, defaultStyleProperties)
2915
3422
  }), {
2916
3423
  drawModeId: 'drawtools-fir',
2917
- title: `Set FIR as ${type} position`,
3424
+ title: translateKeyOutsideComponents('set-a-fir-as', {
3425
+ type
3426
+ }),
2918
3427
  isSelectable: false,
2919
3428
  value: DRAWMODE.POLYGON,
2920
3429
  // add selectionType here to use later for `onUpdateStartgeoJSON` in Sigmet/Airmet-Form when updating form values directly
2921
3430
  shape: addSelectionTypeToGeoJSON(addGeoJSONProperties(firShape, Object.assign({}, defaultStyleProperties)), firSelectionType),
2922
3431
  selectionType: firSelectionType
2923
3432
  }, Object.assign(Object.assign({}, defaultDelete), {
2924
- title: 'Remove geometry'
3433
+ title: translateKeyOutsideComponents('remove-geometry')
2925
3434
  })];
2926
3435
  };
2927
3436
  const updateDrawToolsWithFir = (drawTools, newFirShape) => {
@@ -3064,10 +3573,16 @@ $$9({ global: true, forced: parseInt !== $parseInt }, {
3064
3573
  const DEFAULT_ROUNDING_LEVELS_FL = 5;
3065
3574
  const DEFAULT_ROUNDING_LEVELS_FT = 500;
3066
3575
  const DEFAULT_ROUNDING_LEVELS_M = 1;
3067
- const getLevelInvalidStepsForFLUnitMessage = (value = DEFAULT_ROUNDING_LEVELS_FL) => `Levels must be rounded to the nearest ${value}`;
3068
- const getLevelInvalidStepsForFTUnitMessage = (value = DEFAULT_ROUNDING_LEVELS_FT) => `Levels must be rounded to the nearest ${value}ft`;
3069
- const getLevelInvalidStepsForMUnitMessage = (value = DEFAULT_ROUNDING_LEVELS_M) => `Levels must be rounded to the nearest ${value}m`;
3070
- const invalidUnitMessage$1 = 'Level unit not defined';
3576
+ const getLevelInvalidStepsForFLUnitMessage = (value = DEFAULT_ROUNDING_LEVELS_FL) => translateKeyOutsideComponents('levels-get-level-invalid-steps-for-fl-unit-message', {
3577
+ value
3578
+ });
3579
+ const getLevelInvalidStepsForFTUnitMessage = (value = DEFAULT_ROUNDING_LEVELS_FT) => translateKeyOutsideComponents('levels-get-level-invalid-steps-for-ft-unit-message', {
3580
+ value
3581
+ });
3582
+ const getLevelInvalidStepsForMUnitMessage = (value = DEFAULT_ROUNDING_LEVELS_M) => translateKeyOutsideComponents('levels-get-level-invalid-steps-for-m-unit-message', {
3583
+ value
3584
+ });
3585
+ const invalidUnitMessage$1 = translateKeyOutsideComponents('levels-invalid-unit-message');
3071
3586
  const validateLevels = (value, unit, productConfig, selectedFIR) => {
3072
3587
  if (isEmpty(value)) {
3073
3588
  return true;
@@ -3092,11 +3607,10 @@ const validateLevels = (value, unit, productConfig, selectedFIR) => {
3092
3607
  }
3093
3608
  return invalidUnitMessage$1;
3094
3609
  };
3095
- const invalidLevelUnitCombinationMessage = 'Invalid unit combination';
3096
- const validateLevelUnitCombinations = (levelUnit, lowerLevelUnit) => {
3610
+ const validateLevelUnitCombinations = (levelUnit, lowerLevelUnit, t) => {
3097
3611
  // If different units and lower level not SFC, only FL is allowed as upper level
3098
3612
  if (lowerLevelUnit !== 'SFC' && levelUnit !== lowerLevelUnit && LevelUnits[levelUnit] !== LevelUnits.FL) {
3099
- return invalidLevelUnitCombinationMessage;
3613
+ return t('levels-invalid-level-unit-combination-message');
3100
3614
  }
3101
3615
  return true;
3102
3616
  };
@@ -3106,6 +3620,9 @@ const Levels = ({
3106
3620
  onChange: _onChange = () => {},
3107
3621
  productConfig
3108
3622
  }) => {
3623
+ const {
3624
+ t
3625
+ } = useSigmetAirmetTranslation();
3109
3626
  const {
3110
3627
  watch,
3111
3628
  setValue,
@@ -3140,7 +3657,7 @@ const Levels = ({
3140
3657
  }
3141
3658
  }, [getValues, isRadioactiveCloud, levelInfoMode, radioactiveCloudLevel, setValue, trigger, unregister]);
3142
3659
  return jsx(ProductFormFieldLayout, Object.assign({
3143
- title: "Levels",
3660
+ title: t('levels'),
3144
3661
  sx: styles$2.containerItem
3145
3662
  }, {
3146
3663
  children: jsx(Grid, Object.assign({
@@ -3166,7 +3683,7 @@ const Levels = ({
3166
3683
  }, {
3167
3684
  children: [jsx(RadioButtonAndLabel, {
3168
3685
  value: "AT",
3169
- label: "At",
3686
+ label: t('at'),
3170
3687
  checked: levelInfoMode === 'AT' || levelInfoMode === 'TOPS',
3171
3688
  "data-testid": "levels-AT",
3172
3689
  disabled: fieldsDisabled
@@ -3195,7 +3712,7 @@ const Levels = ({
3195
3712
  disabled: isDisabled
3196
3713
  }),
3197
3714
  "data-testid": "levels-TOPS",
3198
- label: "Tops"
3715
+ label: t('levels-tops-label')
3199
3716
  })
3200
3717
  })), jsx(Grid, Object.assign({
3201
3718
  item: true,
@@ -3204,7 +3721,7 @@ const Levels = ({
3204
3721
  }, {
3205
3722
  children: jsx(ReactHookFormSelect, Object.assign({
3206
3723
  name: "level.unit",
3207
- label: "Unit",
3724
+ label: t('unit-label'),
3208
3725
  rules: {
3209
3726
  validate: {
3210
3727
  isRequired
@@ -3234,17 +3751,23 @@ const Levels = ({
3234
3751
  children: jsx(ReactHookFormNumberField, {
3235
3752
  name: "level.value",
3236
3753
  "data-testid": "level.value",
3237
- label: "Level",
3754
+ label: t('level'),
3238
3755
  rules: {
3239
3756
  validate: {
3240
3757
  isRequired,
3241
3758
  isInteger,
3242
3759
  max: value =>
3243
3760
  // The max level depends on the unit
3244
- isValidMax(value, getMaxLevelValue(getValues('level.unit'), getFIRValue(), productConfig)) || `The maximum level in ${LevelUnits[getValues('level.unit')]} is ${getMaxLevelValue(getValues('level.unit'), getFIRValue(), productConfig)}`,
3761
+ isValidMax(value, getMaxLevelValue(getValues('level.unit'), getFIRValue(), productConfig)) || t('levels-the-maximum-level', {
3762
+ levelUnit: LevelUnits[getValues('level.unit')],
3763
+ maxLevelValue: getMaxLevelValue(getValues('level.unit'), getFIRValue(), productConfig)
3764
+ }),
3245
3765
  min: value =>
3246
3766
  // The min level depends on the unit
3247
- isValidMin(value, getMinLevelValue(getValues('level.unit'), getFIRValue(), productConfig)) || `The minimum level in ${LevelUnits[getValues('level.unit')]} is ${getMinLevelValue(getValues('level.unit'), getFIRValue(), productConfig)}`,
3767
+ isValidMin(value, getMinLevelValue(getValues('level.unit'), getFIRValue(), productConfig)) || t('levels-the-minimum-level', {
3768
+ levelUnit: LevelUnits[getValues('level.unit')],
3769
+ minLevelValue: getMinLevelValue(getValues('level.unit'), getFIRValue(), productConfig)
3770
+ }),
3248
3771
  validateLevels: value =>
3249
3772
  // level step depends on the unit
3250
3773
  validateLevels(value, getValues('level.unit'), productConfig, getFIRValue())
@@ -3258,7 +3781,7 @@ const Levels = ({
3258
3781
  }))]
3259
3782
  })) : null, jsx(RadioButtonAndLabel, {
3260
3783
  value: "BETW",
3261
- label: "Between",
3784
+ label: t('between'),
3262
3785
  checked: levelInfoMode === 'BETW' || levelInfoMode === 'BETW_SFC',
3263
3786
  "data-testid": "levels-BETW",
3264
3787
  disabled: fieldsDisabled
@@ -3280,13 +3803,13 @@ const Levels = ({
3280
3803
  }, {
3281
3804
  children: jsx(ReactHookFormSelect, Object.assign({
3282
3805
  name: "level.unit",
3283
- label: "Unit",
3806
+ label: t('unit-label'),
3284
3807
  rules: {
3285
3808
  validate: {
3286
3809
  isRequired,
3287
3810
  validateLevelUnitCombinations: value =>
3288
3811
  // level step depends on the unit
3289
- validateLevelUnitCombinations(value, levelInfoMode === 'BETW_SFC' ? 'SFC' : getValues('lowerLevel.unit')) === true
3812
+ validateLevelUnitCombinations(value, levelInfoMode === 'BETW_SFC' ? 'SFC' : getValues('lowerLevel.unit'), t) === true
3290
3813
  }
3291
3814
  },
3292
3815
  size: "small",
@@ -3313,7 +3836,7 @@ const Levels = ({
3313
3836
  children: jsx(ReactHookFormNumberField, {
3314
3837
  value: level || '',
3315
3838
  name: "level.value",
3316
- label: "Upper level",
3839
+ label: t('levels-upper-level-label'),
3317
3840
  sx: styles$2.levelField,
3318
3841
  size: "small",
3319
3842
  rules: {
@@ -3322,10 +3845,16 @@ const Levels = ({
3322
3845
  isInteger,
3323
3846
  max: value =>
3324
3847
  // The max level depends on the unit
3325
- isValidMax(value, getMaxLevelValue(getValues('level.unit'), getFIRValue(), productConfig)) || `The maximum level in ${LevelUnits[getValues('level.unit')]} is ${getMaxLevelValue(getValues('level.unit'), getFIRValue(), productConfig)}`,
3848
+ isValidMax(value, getMaxLevelValue(getValues('level.unit'), getFIRValue(), productConfig)) || t('levels-the-maximum-level', {
3849
+ levelUnit: LevelUnits[getValues('level.unit')],
3850
+ maxLevelValue: getMaxLevelValue(getValues('level.unit'), getFIRValue(), productConfig)
3851
+ }),
3326
3852
  min: value =>
3327
3853
  // The min level depends on the unit
3328
- isValidMin(value, getMinLevelValue(getValues('level.unit'), getFIRValue(), productConfig)) || `The minimum level in ${LevelUnits[getValues('level.unit')]} is ${getMinLevelValue(getValues('level.unit'), getFIRValue(), productConfig)}`,
3854
+ isValidMin(value, getMinLevelValue(getValues('level.unit'), getFIRValue(), productConfig)) || t('levels-the-minimum-level', {
3855
+ levelUnit: LevelUnits[getValues('level.unit')],
3856
+ minLevelValue: getMinLevelValue(getValues('level.unit'), getFIRValue(), productConfig)
3857
+ }),
3329
3858
  validateLevels: value =>
3330
3859
  // level step depends on the unit
3331
3860
  validateLevels(value, getValues('level.unit'), productConfig, getFIRValue())
@@ -3376,13 +3905,13 @@ const Levels = ({
3376
3905
  }, {
3377
3906
  children: jsx(ReactHookFormSelect, Object.assign({
3378
3907
  name: "lowerLevel.unit",
3379
- label: "Unit",
3908
+ label: t('unit-label'),
3380
3909
  rules: {
3381
3910
  validate: {
3382
3911
  isRequired,
3383
3912
  validateLevelUnitCombinations: value =>
3384
3913
  // level step depends on the unit
3385
- validateLevelUnitCombinations(getValues('level.unit'), value)
3914
+ validateLevelUnitCombinations(getValues('level.unit'), value, t)
3386
3915
  }
3387
3916
  },
3388
3917
  size: "small",
@@ -3408,17 +3937,23 @@ const Levels = ({
3408
3937
  }, {
3409
3938
  children: jsx(ReactHookFormNumberField, {
3410
3939
  name: "lowerLevel.value",
3411
- label: "Lower level",
3940
+ label: t('levels-lower-level-label'),
3412
3941
  rules: {
3413
3942
  validate: {
3414
3943
  isRequired,
3415
3944
  isInteger,
3416
3945
  max: value =>
3417
3946
  // The max level depends on the unit
3418
- isValidMax(value, getMaxLevelValue(getValues('lowerLevel.unit'), getFIRValue(), productConfig)) || `The maximum level in ${LevelUnits[getValues('lowerLevel.unit')]} is ${getMaxLevelValue(getValues('lowerLevel.unit'), getFIRValue(), productConfig)}`,
3947
+ isValidMax(value, getMaxLevelValue(getValues('lowerLevel.unit'), getFIRValue(), productConfig)) || t('levels-the-maximum-level', {
3948
+ levelUnit: LevelUnits[getValues('lowerLevel.unit')],
3949
+ maxLevelValue: getMaxLevelValue(getValues('lowerLevel.unit'), getFIRValue(), productConfig)
3950
+ }),
3419
3951
  min: value =>
3420
3952
  // The min level depends on the unit
3421
- isValidMin(value, getMinLevelValue(getValues('lowerLevel.unit'), getFIRValue(), productConfig)) || `The minimum level in ${LevelUnits[getValues('lowerLevel.unit')]} is ${getMinLevelValue(getValues('lowerLevel.unit'), getFIRValue(), productConfig)}`,
3953
+ isValidMin(value, getMinLevelValue(getValues('lowerLevel.unit'), getFIRValue(), productConfig)) || t('levels-the-minimum-level', {
3954
+ levelUnit: LevelUnits[getValues('lowerLevel.unit')],
3955
+ minLevelValue: getMinLevelValue(getValues('lowerLevel.unit'), getFIRValue(), productConfig)
3956
+ }),
3422
3957
  isLevelLower: value =>
3423
3958
  // The lower level needs to be smaller than upper level
3424
3959
  isLevelLower(value, getValues('lowerLevel.unit'), getValues('level.value'), getValues('level.unit')),
@@ -3436,7 +3971,7 @@ const Levels = ({
3436
3971
  }))]
3437
3972
  }) : null, jsx(RadioButtonAndLabel, {
3438
3973
  value: "ABV",
3439
- label: "Above",
3974
+ label: t('above'),
3440
3975
  disabled: fieldsDisabled,
3441
3976
  checked: levelInfoMode === 'ABV' || levelInfoMode === 'TOPS_ABV',
3442
3977
  "data-testid": "levels-ABV"
@@ -3463,7 +3998,7 @@ const Levels = ({
3463
3998
  },
3464
3999
  disabled: isDisabled
3465
4000
  }),
3466
- label: "Tops",
4001
+ label: t('levels-tops-label'),
3467
4002
  "data-testid": "levels-TOPS_ABV"
3468
4003
  })
3469
4004
  })), jsx(Grid, Object.assign({
@@ -3473,7 +4008,7 @@ const Levels = ({
3473
4008
  }, {
3474
4009
  children: jsx(ReactHookFormSelect, Object.assign({
3475
4010
  name: "level.unit",
3476
- label: "Unit",
4011
+ label: t('unit-label'),
3477
4012
  rules: {
3478
4013
  validate: {
3479
4014
  isRequired
@@ -3502,17 +4037,23 @@ const Levels = ({
3502
4037
  }, {
3503
4038
  children: jsx(ReactHookFormNumberField, {
3504
4039
  name: "level.value",
3505
- label: "Level",
4040
+ label: t('level'),
3506
4041
  rules: {
3507
4042
  validate: {
3508
4043
  isRequired,
3509
4044
  isInteger,
3510
4045
  max: value =>
3511
4046
  // The max level depends on the unit
3512
- isValidMax(value, getMaxLevelValue(getValues('level.unit'), getFIRValue(), productConfig)) || `The maximum level in ${LevelUnits[getValues('level.unit')]} is ${getMaxLevelValue(getValues('level.unit'), getFIRValue(), productConfig)}`,
4047
+ isValidMax(value, getMaxLevelValue(getValues('level.unit'), getFIRValue(), productConfig)) || t('levels-the-maximum-level', {
4048
+ levelUnit: LevelUnits[getValues('level.unit')],
4049
+ maxLevelValue: getMaxLevelValue(getValues('level.unit'), getFIRValue(), productConfig)
4050
+ }),
3513
4051
  min: value =>
3514
4052
  // The min level depends on the unit
3515
- isValidMin(value, getMinLevelValue(getValues('level.unit'), getFIRValue(), productConfig)) || `The minimum level in ${LevelUnits[getValues('level.unit')]} is ${getMinLevelValue(getValues('level.unit'), getFIRValue(), productConfig)}`,
4053
+ isValidMin(value, getMinLevelValue(getValues('level.unit'), getFIRValue(), productConfig)) || t('levels-the-minimum-level', {
4054
+ levelUnit: LevelUnits[getValues('level.unit')],
4055
+ minLevelValue: getMinLevelValue(getValues('level.unit'), getFIRValue(), productConfig)
4056
+ }),
3516
4057
  validateLevels: value =>
3517
4058
  // level step depends on the unit
3518
4059
  validateLevels(value, getValues('level.unit'), productConfig, getFIRValue())
@@ -3534,6 +4075,9 @@ const ObservationForecast = ({
3534
4075
  isDisabled,
3535
4076
  isReadOnly
3536
4077
  }) => {
4078
+ const {
4079
+ t
4080
+ } = useSigmetAirmetTranslation();
3537
4081
  const {
3538
4082
  watch,
3539
4083
  trigger,
@@ -3571,12 +4115,12 @@ const ObservationForecast = ({
3571
4115
  }, {
3572
4116
  children: [(!isReadOnly || watch('isObservationOrForecast') === 'OBS') && jsx(RadioButtonAndLabel, {
3573
4117
  value: "OBS",
3574
- label: "Observed",
4118
+ label: t('observation-label'),
3575
4119
  disabled: fieldsDisabled,
3576
4120
  "data-testid": "isObservationOrForecast-OBS"
3577
4121
  }), (!isReadOnly || watch('isObservationOrForecast') === 'FCST') && jsx(RadioButtonAndLabel, {
3578
4122
  value: "FCST",
3579
- label: "Forecast",
4123
+ label: t('forecast-label'),
3580
4124
  disabled: fieldsDisabled,
3581
4125
  "data-testid": "isObservationOrForecast-FCST"
3582
4126
  })]
@@ -3584,7 +4128,6 @@ const ObservationForecast = ({
3584
4128
  }));
3585
4129
  };
3586
4130
 
3587
- const ForecastTimeValidation = 'Forecast time should lie between the valid start and valid end time';
3588
4131
  const goZeroSeconds = val => {
3589
4132
  return dateUtils.dateToString(dateUtils.set(dateUtils.utc(val), {
3590
4133
  seconds: 0,
@@ -3597,16 +4140,20 @@ const ObservationForecastTime = ({
3597
4140
  helperText,
3598
4141
  onChange: _onChange = () => {}
3599
4142
  }) => {
4143
+ const {
4144
+ t
4145
+ } = useSigmetAirmetTranslation();
3600
4146
  const {
3601
4147
  watch
3602
4148
  } = useFormContext();
3603
- const label = getFieldLabel('Date and time', isReadOnly);
4149
+ const label = getFieldLabel(t('date-and-time'), isReadOnly);
3604
4150
  const {
3605
4151
  isShortTest
3606
4152
  } = useShortTestHelpers();
3607
4153
  const fieldsDisabled = isDisabled || isShortTest();
4154
+ const forecastValidationMessage = t('surface-visibility-between-time');
3608
4155
  return !isReadOnly || watch('observationOrForecastTime') !== null ? jsx(ProductFormFieldLayout, Object.assign({
3609
- title: "At"
4156
+ title: t('at')
3610
4157
  }, {
3611
4158
  children: jsx(ReactHookFormDateTime, {
3612
4159
  disablePast: watch('isObservationOrForecast') === 'FCST',
@@ -3616,8 +4163,8 @@ const ObservationForecastTime = ({
3616
4163
  rules: {
3617
4164
  validate: {
3618
4165
  isValidDate: dateUtils.isValidIsoDateString,
3619
- isBefore: val => watch('isObservationOrForecast') === 'OBS' && val ? dateUtils.isBefore(val, dateUtils.getNowUtc()) || 'Observation time cannot be in the future' : true,
3620
- isBetween: val => watch('isObservationOrForecast') === 'FCST' && val ? dateUtils.isBetween(dateUtils.isoStringToDate(val), dateUtils.isoStringToDate(goZeroSeconds(watch('validDateStart'))), dateUtils.isoStringToDate(goZeroSeconds(watch('validDateEnd'))), '[]') || ForecastTimeValidation : true
4166
+ isBefore: val => watch('isObservationOrForecast') === 'OBS' && val ? dateUtils.isBefore(val, dateUtils.getNowUtc()) || t('observation-forecast-error') : true,
4167
+ isBetween: val => watch('isObservationOrForecast') === 'FCST' && val ? dateUtils.isBetween(dateUtils.isoStringToDate(val), dateUtils.isoStringToDate(goZeroSeconds(watch('validDateStart'))), dateUtils.isoStringToDate(goZeroSeconds(watch('validDateEnd'))), '[]') || forecastValidationMessage : true
3621
4168
  }
3622
4169
  },
3623
4170
  disabled: fieldsDisabled,
@@ -3636,6 +4183,9 @@ const Phenomenon = ({
3636
4183
  isReadOnly,
3637
4184
  onChange: _onChange = () => {}
3638
4185
  }) => {
4186
+ const {
4187
+ t
4188
+ } = useSigmetAirmetTranslation();
3639
4189
  const {
3640
4190
  getValues,
3641
4191
  setValue,
@@ -3646,10 +4196,10 @@ const Phenomenon = ({
3646
4196
  } = useShortTestHelpers();
3647
4197
  const isSigmet = productType === 'sigmet';
3648
4198
  const phenomenaList = isSigmet ? SigmetPhenomena : AirmetPhenomena;
3649
- const label = getFieldLabel('Phenomenon', isReadOnly);
4199
+ const label = getFieldLabel(t('phenomenon'), isReadOnly);
3650
4200
  const fieldsDisabled = isDisabled || isShortTest();
3651
4201
  return jsx(ProductFormFieldLayout, Object.assign({
3652
- title: "What"
4202
+ title: t('phenomenon-title')
3653
4203
  }, {
3654
4204
  children: jsx(ReactHookFormSelect, Object.assign({
3655
4205
  name: "phenomenon",
@@ -3684,115 +4234,14 @@ const Phenomenon = ({
3684
4234
  }));
3685
4235
  };
3686
4236
 
3687
- const coordinatesEmptyMessage$1 = 'A start position drawing is required';
3688
- const noIntersectionMessage$1 = 'The start position needs to be (partly) inside the FIR';
3689
- const exitDrawModeMessage = 'Press ESC to exit draw mode';
3690
- const maxFeaturePointsMessage = 'Intersection of the drawn polygon with the FIR-boundary has more than 6 individual points. Check if the TAC in the preview corresponds to the intended area.';
3691
- const multiIntersectionsMessage = 'The drawn polygon has multiple intersections with the FIR-boundary. The drawn polygon will be used for the TAC-code.';
3692
- const StartGeometry = ({
3693
- isReadOnly: _isReadOnly = false,
3694
- activeTool,
3695
- tools,
3696
- onChangeTool,
3697
- geoJSON,
3698
- geoJSONIntersection,
3699
- productConfig
3700
- }) => {
3701
- var _a, _b;
3702
- const {
3703
- formState: {
3704
- errors
3705
- },
3706
- watch,
3707
- getValues
3708
- } = useFormContext();
3709
- const {
3710
- isDraft
3711
- } = useDraftFormHelpers();
3712
- const {
3713
- isShortTest
3714
- } = useShortTestHelpers();
3715
- const getFIRValue = () => getValues('locationIndicatorATSR');
3716
- // Max points the FIR allows for a polygon
3717
- const maxPoints = getMaxPolygonPoints(getFIRValue(), productConfig);
3718
- // Intersections with FIR
3719
- const intersectionPointCount = countIntersectionPoints(geoJSON, geoJSONIntersection);
3720
- const drawnGeometry = (_a = geoJSON === null || geoJSON === void 0 ? void 0 : geoJSON.features[0]) === null || _a === void 0 ? void 0 : _a.geometry;
3721
- const interceptionGeometry = (_b = geoJSONIntersection === null || geoJSONIntersection === void 0 ? void 0 : geoJSONIntersection.features[0]) === null || _b === void 0 ? void 0 : _b.geometry;
3722
- // Total points in the user drawn polygon
3723
- const totalDrawnPoints = drawnGeometry && drawnGeometry.coordinates[0] ? drawnGeometry.coordinates[0].length : 0;
3724
- // Total points in the intersection polygon
3725
- const intersectingPolygonPointsTotal = interceptionGeometry && interceptionGeometry.coordinates[0] ? interceptionGeometry.coordinates[0].length : 0;
3726
- const maximumPointsMessage = `The start position drawing allows a maximum of ${maxPoints - 1} individual points`;
3727
- const moreThan6PointsMessage = `The start/end position drawing has exceeded 6 individual points. The TAC has a total of ${totalDrawnPoints} points. If possible, reduce the number of points.`;
3728
- const intersectionAbove6PointsMessage = `The start/end position of the intersected polygon has
3729
- ${intersectingPolygonPointsTotal} points,
3730
- and the intersection of the drawn polygon with the FIR-boundary has exceeded 6 individual points.
3731
- Check if the TAC in the preview corresponds to the intended area.`;
3732
- const showMaxFeaturePointsWarning = intersectionPointCount > 7 && hasMaxFeaturePoints(geoJSONIntersection, maxPoints) && !activeTool && !errors.startGeometry && !isFir(geoJSON);
3733
- const showMoreThan6PointsWarning = totalDrawnPoints > 7 && intersectionPointCount < 1 && !activeTool && !errors.startGeometry && !isFir(geoJSON);
3734
- const showIntersectionAbove6PointsWarning = intersectingPolygonPointsTotal > 7 && intersectionPointCount > 6 && maxPoints > 7 && !activeTool && !errors.startGeometry && !isFir(geoJSON);
3735
- return !_isReadOnly ? jsxs(ProductFormFieldLayout, Object.assign({
3736
- title: "Start position",
3737
- sx: styles$2.drawSection,
3738
- "data-testid": "startGeometry"
3739
- }, {
3740
- children: [jsx(DrawTools, {
3741
- activeTool: activeTool,
3742
- tools: tools,
3743
- onChangeTool: onChangeTool,
3744
- isDisabled: isShortTest()
3745
- }), activeTool && jsx(FormHelperText, Object.assign({
3746
- variant: "filled",
3747
- sx: styles$2.quitDrawModeMessage
3748
- }, {
3749
- children: exitDrawModeMessage
3750
- })), !!errors.startGeometry && jsx(FormHelperText, Object.assign({
3751
- error: true,
3752
- variant: "filled"
3753
- }, {
3754
- children: errors.startGeometry.message
3755
- })), /* non-blocking warnings */
3756
- showMaxFeaturePointsWarning && jsx(FormHelperText, Object.assign({
3757
- variant: "filled"
3758
- }, {
3759
- children: maxFeaturePointsMessage
3760
- })), /* non-blocking warnings */
3761
- showMoreThan6PointsWarning && jsx(FormHelperText, Object.assign({
3762
- variant: "filled"
3763
- }, {
3764
- children: moreThan6PointsMessage
3765
- })), /* non-blocking warnings */
3766
- showIntersectionAbove6PointsWarning && jsx(FormHelperText, Object.assign({
3767
- variant: "filled"
3768
- }, {
3769
- children: intersectionAbove6PointsMessage
3770
- })), hasMulitpleIntersections(geoJSONIntersection) && !activeTool && !errors.startGeometry && !isFir(geoJSON) && jsx(FormHelperText, Object.assign({
3771
- variant: "filled"
3772
- }, {
3773
- children: multiIntersectionsMessage
3774
- })), jsx(ReactHookFormHiddenInput, {
3775
- name: "startGeometry",
3776
- rules: {
3777
- validate: {
3778
- maximumOneDrawing: value => isMaximumOneDrawing(value) || 'Only one start position drawing is allowed',
3779
- intersectWithFIR: value => hasIntersectionWithFIR(value, watch('startGeometryIntersect')) || noIntersectionMessage$1,
3780
- coordinatesNotEmpty: value => isDraft() || isShortTest() ? true : isValidGeoJsonCoordinates(value) || coordinatesEmptyMessage$1,
3781
- hasMaxFeaturePoints: value => isFir(value) ? true : !hasMaxFeaturePoints(value, maxPoints) || maximumPointsMessage
3782
- }
3783
- }
3784
- }), jsx(ReactHookFormHiddenInput, {
3785
- name: "startGeometryIntersect"
3786
- })]
3787
- })) : null;
3788
- };
3789
-
3790
4237
  const DEFAULT_ROUNDING_MOVEMENT_KT = 5;
3791
4238
  const DEFAULT_ROUNDING_MOVEMENT_KMH = 10;
3792
- const getMovementStepValKTMessage = (value = DEFAULT_ROUNDING_MOVEMENT_KT) => `Speed should be rounded to the nearest ${value}kt`;
3793
- const getMovementStepValKMHMessage = (value = DEFAULT_ROUNDING_MOVEMENT_KMH) => `Speed should be rounded to the nearest ${value}kmh`;
3794
- const coordinatesEmptyMessage = 'An end position drawing is required when selecting End position';
3795
- const noIntersectionMessage = 'The end position needs to be (partly) inside the FIR';
4239
+ const getMovementStepValKTMessage = (value = DEFAULT_ROUNDING_MOVEMENT_KT) => translateKeyOutsideComponents('progress-get-movement-step-valktmessage', {
4240
+ value
4241
+ });
4242
+ const getMovementStepValKMHMessage = (value = DEFAULT_ROUNDING_MOVEMENT_KMH) => translateKeyOutsideComponents('progress-get-movement-step-valkmhmessage', {
4243
+ value
4244
+ });
3796
4245
  const validateMovementSteps = (value, unit, productConfig, selectedFIR) => {
3797
4246
  if (isEmpty(value)) {
3798
4247
  return true;
@@ -3811,7 +4260,7 @@ const validateMovementSteps = (value, unit, productConfig, selectedFIR) => {
3811
4260
  if (MovementUnit[unit] === MovementUnit.KMH) {
3812
4261
  return intLevel % movement_rounding_kmh === 0 || getMovementStepValKMHMessage(movement_rounding_kmh);
3813
4262
  }
3814
- return 'Invalid unit';
4263
+ return translateKeyOutsideComponents('invalid-unit');
3815
4264
  };
3816
4265
  const Progress = ({
3817
4266
  productType,
@@ -3826,6 +4275,9 @@ const Progress = ({
3826
4275
  geoJSONIntersection
3827
4276
  }) => {
3828
4277
  var _a, _b;
4278
+ const {
4279
+ t
4280
+ } = useSigmetAirmetTranslation();
3829
4281
  const {
3830
4282
  watch,
3831
4283
  getValues,
@@ -3873,17 +4325,11 @@ const Progress = ({
3873
4325
  const totalDrawnPoints = drawnGeometry && drawnGeometry.coordinates[0] ? drawnGeometry.coordinates[0].length : 0;
3874
4326
  // Total points in the intersection polygon
3875
4327
  const intersectingPolygonPointsTotal = interceptionGeometry && interceptionGeometry.coordinates[0] ? interceptionGeometry.coordinates[0].length : 0;
3876
- const maximumPointsMessage = `The end position drawing allows a maximum of ${maxPoints - 1} individual points`;
3877
- const moreThan6PointsMessage = `The start/end position drawing has exceeded 6 individual points. The TAC has a total of ${totalDrawnPoints} points. If possible, reduce the number of points.`;
3878
- const intersectionAbove6PointsMessage = `The start/end position of the intersected polygon has
3879
- ${intersectingPolygonPointsTotal} points,
3880
- and the intersection of the drawn polygon with the FIR-boundary has exceeded 6 individual points.
3881
- Check if the TAC in the preview corresponds to the intended area.`;
3882
4328
  const showMaxFeaturePointsWarning = intersectionPointCount > 7 && hasMaxFeaturePoints(geoJSONIntersection, maxPoints) && !activeTool && !errors.startGeometry && !isFir(geoJSON);
3883
4329
  const showMoreThan6PointsWarning = totalDrawnPoints > 7 && intersectionPointCount < 1 && !activeTool && !errors.startGeometry && !isFir(geoJSON);
3884
4330
  const showIntersectionAbove6PointsWarning = intersectingPolygonPointsTotal > 7 && intersectionPointCount > 6 && maxPoints > 7 && !activeTool && !errors.startGeometry && !isFir(geoJSON);
3885
4331
  return jsx(ProductFormFieldLayout, Object.assign({
3886
- title: "Progress",
4332
+ title: t('progress'),
3887
4333
  sx: styles$2.containerItem
3888
4334
  }, {
3889
4335
  children: jsxs(Grid, Object.assign({
@@ -3908,23 +4354,23 @@ const Progress = ({
3908
4354
  }, {
3909
4355
  children: [isVolcanicCloud && jsx(RadioButtonAndLabel, {
3910
4356
  value: "NO_VA_EXP",
3911
- label: "No volcanic ash expected",
4357
+ label: t('progress-radio-button-label-no-va-exp'),
3912
4358
  disabled: fieldsDisabled,
3913
4359
  "data-testid": "movementType-NO_VA_EXP"
3914
4360
  }), jsxs(Fragment, {
3915
4361
  children: [jsx(RadioButtonAndLabel, {
3916
4362
  value: "STATIONARY",
3917
- label: "Stationary",
4363
+ label: t('progress-radio-button-label-stationary'),
3918
4364
  disabled: fieldsDisabled,
3919
4365
  "data-testid": "movementType-STATIONARY"
3920
4366
  }), jsx(RadioButtonAndLabel, {
3921
4367
  value: "MOVEMENT",
3922
- label: "Movement",
4368
+ label: t('progress-radio-button-label-movement'),
3923
4369
  disabled: fieldsDisabled,
3924
4370
  "data-testid": "movementType-MOVEMENT"
3925
4371
  }), isSigmet && isShortTestOrRdoact && jsx(RadioButtonAndLabel, {
3926
4372
  value: "FORECAST_POSITION",
3927
- label: "End position",
4373
+ label: t('progress-radio-button-label-end-potision'),
3928
4374
  disabled: fieldsDisabled,
3929
4375
  "data-testid": "movementType-FORECAST_POSITION"
3930
4376
  })]
@@ -3935,7 +4381,7 @@ const Progress = ({
3935
4381
  }, {
3936
4382
  children: jsx(ReactHookFormSelect, Object.assign({
3937
4383
  name: "movementDirection",
3938
- label: "Set direction",
4384
+ label: t('progress-movement-direction-label'),
3939
4385
  rules: {
3940
4386
  validate: {
3941
4387
  isRequired
@@ -3969,7 +4415,7 @@ const Progress = ({
3969
4415
  }, {
3970
4416
  children: jsx(ReactHookFormSelect, Object.assign({
3971
4417
  name: "movementUnit",
3972
- label: "Unit",
4418
+ label: t('progress-movement-unit-label'),
3973
4419
  rules: {
3974
4420
  validate: {
3975
4421
  isRequired
@@ -3999,17 +4445,23 @@ const Progress = ({
3999
4445
  }, {
4000
4446
  children: jsx(ReactHookFormNumberField, {
4001
4447
  name: "movementSpeed",
4002
- label: "Step speed",
4448
+ label: t('progress-movement-speed-label'),
4003
4449
  rules: {
4004
4450
  validate: {
4005
4451
  isRequired,
4006
4452
  isInteger,
4007
4453
  min: value =>
4008
4454
  // The max level depends on the unit
4009
- isValidMin(value, getMinMovementSpeedValue(getValues('movementUnit'), getFIRValue(), productConfig)) || `The minimum level in ${MovementUnit[getValues('movementUnit')]} is ${getMinMovementSpeedValue(getValues('movementUnit'), getFIRValue(), productConfig)}`,
4455
+ isValidMin(value, getMinMovementSpeedValue(getValues('movementUnit'), getFIRValue(), productConfig)) || t('progress-the-minimum-level-in-movement', {
4456
+ movementUnitType: MovementUnit[getValues('movementUnit')],
4457
+ movementUnit: getMinMovementSpeedValue(getValues('movementUnit'), getFIRValue(), productConfig)
4458
+ }),
4010
4459
  max: value =>
4011
4460
  // The max level depends on the unit
4012
- isValidMax(value, getMaxMovementSpeedValue(getValues('movementUnit'), getFIRValue(), productConfig)) || `The maximum level in ${MovementUnit[getValues('movementUnit')]} is ${getMaxMovementSpeedValue(getValues('movementUnit'), getFIRValue(), productConfig)}`,
4461
+ isValidMax(value, getMaxMovementSpeedValue(getValues('movementUnit'), getFIRValue(), productConfig)) || t('progress-the-maxium-level-in-movement', {
4462
+ movementUnitType: MovementUnit[getValues('movementUnit')],
4463
+ movementUnit: getMaxMovementSpeedValue(getValues('movementUnit'), getFIRValue(), productConfig)
4464
+ }),
4013
4465
  validateMovementSteps: value =>
4014
4466
  // movement step depends on the unit
4015
4467
  validateMovementSteps(value, getValues('movementUnit'), productConfig, getFIRValue())
@@ -4025,7 +4477,7 @@ const Progress = ({
4025
4477
  }))]
4026
4478
  }), isSigmet && !isShortTestOrRdoact && jsx(RadioButtonAndLabel, {
4027
4479
  value: "FORECAST_POSITION",
4028
- label: "End position",
4480
+ label: t('progress-radio-button-label-end-potision'),
4029
4481
  disabled: _isDisabled,
4030
4482
  "data-testid": "movementType-FORECAST_POSITION"
4031
4483
  })]
@@ -4045,7 +4497,7 @@ const Progress = ({
4045
4497
  variant: "filled",
4046
4498
  sx: styles$2.quitDrawModeMessage
4047
4499
  }, {
4048
- children: exitDrawModeMessage
4500
+ children: t('geometry-exit-draw-mode-message')
4049
4501
  })), !!errors.endGeometry && jsx(FormHelperText, Object.assign({
4050
4502
  error: true,
4051
4503
  variant: "filled"
@@ -4055,30 +4507,36 @@ const Progress = ({
4055
4507
  showMaxFeaturePointsWarning && jsx(FormHelperText, Object.assign({
4056
4508
  variant: "filled"
4057
4509
  }, {
4058
- children: maxFeaturePointsMessage
4510
+ children: t('geometry-max-feature-points-message')
4059
4511
  })), /* non-blocking warnings */
4060
4512
  showMoreThan6PointsWarning && jsx(FormHelperText, Object.assign({
4061
4513
  variant: "filled"
4062
4514
  }, {
4063
- children: moreThan6PointsMessage
4515
+ children: t('progress-more-than-6-points-message', {
4516
+ totalDrawnPoints
4517
+ })
4064
4518
  })), /* non-blocking warnings */
4065
4519
  showIntersectionAbove6PointsWarning && jsx(FormHelperText, Object.assign({
4066
4520
  variant: "filled"
4067
4521
  }, {
4068
- children: intersectionAbove6PointsMessage
4522
+ children: t('progress-intersection-above-6-points-message', {
4523
+ intersectingPolygonPointsTotal
4524
+ })
4069
4525
  })), hasMulitpleIntersections(geoJSONIntersection) && !activeTool && !errors.endGeometry && !isFir(geoJSON) && jsx(FormHelperText, Object.assign({
4070
4526
  variant: "filled"
4071
4527
  }, {
4072
- children: multiIntersectionsMessage
4528
+ children: t('geometry-multi-intersections-message')
4073
4529
  }))]
4074
4530
  }), jsx(ReactHookFormHiddenInput, {
4075
4531
  name: "endGeometry",
4076
4532
  rules: {
4077
4533
  validate: {
4078
- maximumOneDrawing: value => isMaximumOneDrawing(value) || 'Only one end position drawing is allowed',
4079
- coordinatesNotEmpty: value => getValues('movementType') === 'FORECAST_POSITION' && !isDraft() ? isValidGeoJsonCoordinates(value) || coordinatesEmptyMessage : true,
4080
- intersectWithFIR: value => hasIntersectionWithFIR(value, getValues('endGeometryIntersect')) || noIntersectionMessage,
4081
- hasMaxFeaturePoints: value => isFir(value) ? true : !hasMaxFeaturePoints(value, maxPoints) || maximumPointsMessage
4534
+ maximumOneDrawing: value => isMaximumOneDrawing(value) || t('progress-only-one-position-drawing'),
4535
+ coordinatesNotEmpty: value => getValues('movementType') === 'FORECAST_POSITION' && !isDraft() ? isValidGeoJsonCoordinates(value) || t('progress-coordinate-empty-message') : true,
4536
+ intersectWithFIR: value => hasIntersectionWithFIR(value, getValues('endGeometryIntersect')) || t('progress-no-intersection-message'),
4537
+ hasMaxFeaturePoints: value => isFir(value) ? true : !hasMaxFeaturePoints(value, maxPoints) || t('progress-maximumPointsMessage', {
4538
+ maxPoints: maxPoints - 1
4539
+ })
4082
4540
  }
4083
4541
  }
4084
4542
  }), jsx(ReactHookFormHiddenInput, {
@@ -4111,6 +4569,9 @@ const SelectFIR = ({
4111
4569
  isReadOnly,
4112
4570
  onChange: _onChange = () => {}
4113
4571
  }) => {
4572
+ const {
4573
+ t
4574
+ } = useSigmetAirmetTranslation();
4114
4575
  const {
4115
4576
  setValue,
4116
4577
  trigger,
@@ -4143,11 +4604,11 @@ const SelectFIR = ({
4143
4604
  _onChange(changeEvent);
4144
4605
  };
4145
4606
  return jsxs(ProductFormFieldLayout, Object.assign({
4146
- title: "Where"
4607
+ title: t('select-fir-title')
4147
4608
  }, {
4148
4609
  children: [jsx(ReactHookFormSelect, Object.assign({
4149
4610
  name: "locationIndicatorATSR",
4150
- label: isReadOnly ? 'FIR' : 'Select FIR',
4611
+ label: isReadOnly ? 'FIR' : t('select-fir-label'),
4151
4612
  rules: {
4152
4613
  validate: {
4153
4614
  isRequired
@@ -4184,23 +4645,127 @@ const SelectFIR = ({
4184
4645
  }));
4185
4646
  };
4186
4647
 
4648
+ const StartGeometry = ({
4649
+ isReadOnly: _isReadOnly = false,
4650
+ activeTool,
4651
+ tools,
4652
+ onChangeTool,
4653
+ geoJSON,
4654
+ geoJSONIntersection,
4655
+ productConfig
4656
+ }) => {
4657
+ var _a, _b;
4658
+ const {
4659
+ t
4660
+ } = useSigmetAirmetTranslation();
4661
+ const {
4662
+ formState: {
4663
+ errors
4664
+ },
4665
+ watch,
4666
+ getValues
4667
+ } = useFormContext();
4668
+ const {
4669
+ isDraft
4670
+ } = useDraftFormHelpers();
4671
+ const {
4672
+ isShortTest
4673
+ } = useShortTestHelpers();
4674
+ const getFIRValue = () => getValues('locationIndicatorATSR');
4675
+ // Max points the FIR allows for a polygon
4676
+ const maxPoints = getMaxPolygonPoints(getFIRValue(), productConfig);
4677
+ // Intersections with FIR
4678
+ const intersectionPointCount = countIntersectionPoints(geoJSON, geoJSONIntersection);
4679
+ const drawnGeometry = (_a = geoJSON === null || geoJSON === void 0 ? void 0 : geoJSON.features[0]) === null || _a === void 0 ? void 0 : _a.geometry;
4680
+ const interceptionGeometry = (_b = geoJSONIntersection === null || geoJSONIntersection === void 0 ? void 0 : geoJSONIntersection.features[0]) === null || _b === void 0 ? void 0 : _b.geometry;
4681
+ // Total points in the user drawn polygon
4682
+ const totalDrawnPoints = drawnGeometry && drawnGeometry.coordinates[0] ? drawnGeometry.coordinates[0].length : 0;
4683
+ // Total points in the intersection polygon
4684
+ const intersectingPolygonPointsTotal = interceptionGeometry && interceptionGeometry.coordinates[0] ? interceptionGeometry.coordinates[0].length : 0;
4685
+ const showMaxFeaturePointsWarning = intersectionPointCount > 7 && hasMaxFeaturePoints(geoJSONIntersection, maxPoints) && !activeTool && !errors.startGeometry && !isFir(geoJSON);
4686
+ const showMoreThan6PointsWarning = totalDrawnPoints > 7 && intersectionPointCount < 1 && !activeTool && !errors.startGeometry && !isFir(geoJSON);
4687
+ const showIntersectionAbove6PointsWarning = intersectingPolygonPointsTotal > 7 && intersectionPointCount > 6 && maxPoints > 7 && !activeTool && !errors.startGeometry && !isFir(geoJSON);
4688
+ return !_isReadOnly ? jsxs(ProductFormFieldLayout, Object.assign({
4689
+ title: t('start-position'),
4690
+ sx: styles$2.drawSection,
4691
+ "data-testid": "startGeometry"
4692
+ }, {
4693
+ children: [jsx(DrawTools, {
4694
+ activeTool: activeTool,
4695
+ tools: tools,
4696
+ onChangeTool: onChangeTool,
4697
+ isDisabled: isShortTest()
4698
+ }), activeTool && jsx(FormHelperText, Object.assign({
4699
+ variant: "filled",
4700
+ sx: styles$2.quitDrawModeMessage
4701
+ }, {
4702
+ children: t('geometry-exit-draw-mode-message')
4703
+ })), !!errors.startGeometry && jsx(FormHelperText, Object.assign({
4704
+ error: true,
4705
+ variant: "filled"
4706
+ }, {
4707
+ children: errors.startGeometry.message
4708
+ })), /* non-blocking warnings */
4709
+ showMaxFeaturePointsWarning && jsx(FormHelperText, Object.assign({
4710
+ variant: "filled"
4711
+ }, {
4712
+ children: t('geometry-max-feature-points-message')
4713
+ })), /* non-blocking warnings */
4714
+ showMoreThan6PointsWarning && jsx(FormHelperText, Object.assign({
4715
+ variant: "filled"
4716
+ }, {
4717
+ children: t('geometry-more-than-6-points-message', {
4718
+ totalDrawnPoints
4719
+ })
4720
+ })), /* non-blocking warnings */
4721
+ showIntersectionAbove6PointsWarning && jsx(FormHelperText, Object.assign({
4722
+ variant: "filled"
4723
+ }, {
4724
+ children: t('geometry-intersection-above-6-points-message', {
4725
+ intersectingPolygonPointsTotal
4726
+ })
4727
+ })), hasMulitpleIntersections(geoJSONIntersection) && !activeTool && !errors.startGeometry && !isFir(geoJSON) && jsx(FormHelperText, Object.assign({
4728
+ variant: "filled"
4729
+ }, {
4730
+ children: t('geometry-multi-intersections-message')
4731
+ })), jsx(ReactHookFormHiddenInput, {
4732
+ name: "startGeometry",
4733
+ rules: {
4734
+ validate: {
4735
+ maximumOneDrawing: value => isMaximumOneDrawing(value) || t('geometry-only-one-start-position-drawing'),
4736
+ intersectWithFIR: value => hasIntersectionWithFIR(value, watch('startGeometryIntersect')) || t('geometry-no-intersection-message'),
4737
+ coordinatesNotEmpty: value => isDraft() || isShortTest() ? true : isValidGeoJsonCoordinates(value) || t('geometry-coodinates-empty-message'),
4738
+ hasMaxFeaturePoints: value => isFir(value) ? true : !hasMaxFeaturePoints(value, maxPoints) || t('geometry-maximum-points-message', {
4739
+ maxPoints: maxPoints - 1
4740
+ })
4741
+ }
4742
+ }
4743
+ }), jsx(ReactHookFormHiddenInput, {
4744
+ name: "startGeometryIntersect"
4745
+ })]
4746
+ })) : null;
4747
+ };
4748
+
4187
4749
  const Type = ({
4188
4750
  productType,
4189
4751
  isReadOnly,
4190
4752
  isDisabled,
4191
4753
  onChange: _onChange = () => {}
4192
4754
  }) => {
4755
+ const {
4756
+ t
4757
+ } = useSigmetAirmetTranslation();
4193
4758
  const {
4194
4759
  getValues,
4195
4760
  trigger
4196
4761
  } = useFormContext();
4197
- const label = getFieldLabel('Type', isReadOnly);
4762
+ const label = getFieldLabel(t('type-title'), isReadOnly);
4198
4763
  const {
4199
4764
  onTypeChange
4200
4765
  } = useShortTestHelpers();
4201
4766
  const messageType = productType === 'airmet' ? AirmetType : SigmetType;
4202
4767
  return jsx(ProductFormFieldLayout, Object.assign({
4203
- title: "Type"
4768
+ title: t('type-title')
4204
4769
  }, {
4205
4770
  children: jsx(ReactHookFormSelect, Object.assign({
4206
4771
  name: "type",
@@ -4226,8 +4791,9 @@ const Type = ({
4226
4791
  }));
4227
4792
  };
4228
4793
 
4229
- const VALID_FROM_ERROR_BEFORE_CURRENT = 'Valid from time cannot be before current time';
4230
- const getValidFromXHoursBeforeMessage = hours => `Valid from time can be no more than ${hours} hours after current time`;
4794
+ const getValidFromXHoursBeforeMessage = hours => translateKeyOutsideComponents('valid-from-time-error', {
4795
+ hours
4796
+ });
4231
4797
  const getDefaultValidFromValue = productConfig => {
4232
4798
  const validFromDelayTimeMinutes = getValidFromDelayTimeMinutesFromConfig(productConfig);
4233
4799
  return dateUtils.dateToString(dateUtils.add(dateUtils.utc(), {
@@ -4240,6 +4806,9 @@ const ValidFrom = ({
4240
4806
  isReadOnly,
4241
4807
  onChange: _onChange = () => {}
4242
4808
  }) => {
4809
+ const {
4810
+ t
4811
+ } = useSigmetAirmetTranslation();
4243
4812
  const {
4244
4813
  getValues,
4245
4814
  trigger
@@ -4247,9 +4816,9 @@ const ValidFrom = ({
4247
4816
  const {
4248
4817
  isRequired
4249
4818
  } = useDraftFormHelpers();
4250
- const label = getFieldLabel('Date and time', isReadOnly);
4819
+ const label = getFieldLabel(t('date-and-time'), isReadOnly);
4251
4820
  return jsx(ProductFormFieldLayout, Object.assign({
4252
- title: "Valid from"
4821
+ title: t('valid-from')
4253
4822
  }, {
4254
4823
  children: jsx(ReactHookFormDateTime, {
4255
4824
  disablePast: true,
@@ -4261,7 +4830,7 @@ const ValidFrom = ({
4261
4830
  isRequired,
4262
4831
  isValidDate: dateUtils.isValidIsoDateString,
4263
4832
  // The validity start can not be before the current time
4264
- isValueBeforeCurrentTime: value => isXHoursBefore(value, dateUtils.getCurrentTimeAsString(), 0) || VALID_FROM_ERROR_BEFORE_CURRENT,
4833
+ isValueBeforeCurrentTime: value => isXHoursBefore(value, dateUtils.getCurrentTimeAsString(), 0) || t('valid-from-before-current-error'),
4265
4834
  // The current time can be no more than 4 hours before the validity start (12 for VA/TC SIGMET)
4266
4835
  isCurrentTimeXHoursBeforeValue: value => isXHoursBefore(dateUtils.getCurrentTimeAsString(), value, getHoursBeforeValidity(getValues('phenomenon'), getValues('locationIndicatorATSR'), productConfig)) || getValidFromXHoursBeforeMessage(getHoursBeforeValidity(getValues('phenomenon'), getValues('locationIndicatorATSR'), productConfig))
4267
4836
  }
@@ -4291,6 +4860,9 @@ const ValidUntil = ({
4291
4860
  isReadOnly,
4292
4861
  onChange: _onChange = () => {}
4293
4862
  }) => {
4863
+ const {
4864
+ t
4865
+ } = useSigmetAirmetTranslation();
4294
4866
  const {
4295
4867
  getValues,
4296
4868
  trigger
@@ -4298,9 +4870,10 @@ const ValidUntil = ({
4298
4870
  const {
4299
4871
  isRequired
4300
4872
  } = useDraftFormHelpers();
4301
- const label = getFieldLabel('Date and time', isReadOnly);
4873
+ const dateAndTime = t('date-and-time');
4874
+ const label = getFieldLabel(dateAndTime, isReadOnly);
4302
4875
  return jsx(ProductFormFieldLayout, Object.assign({
4303
- title: "Valid until"
4876
+ title: t('valid-until')
4304
4877
  }, {
4305
4878
  children: jsx(ReactHookFormDateTime, {
4306
4879
  disablePast: true,
@@ -4312,9 +4885,11 @@ const ValidUntil = ({
4312
4885
  isRequired,
4313
4886
  isValidDate: dateUtils.isValidIsoDateString,
4314
4887
  // Validity end has to be after validity start
4315
- isAfter: value => value ? dateUtils.isAfter(value, getValues('validDateStart')) || 'Valid until time has to be after Valid from time' : true,
4888
+ isAfter: value => value ? dateUtils.isAfter(value, getValues('validDateStart')) || t('valid-until-time') : true,
4316
4889
  // Validity end can be no more than 4 hours after validity start (6 for VA/TC SIGMET)
4317
- isXHoursAfter: value => isXHoursAfter(value, getValues('validDateStart'), getMaxHoursOfValidity(getValues('phenomenon'), getValues('locationIndicatorATSR'), productConfig)) || `Valid until time can be no more than ${getMaxHoursOfValidity(getValues('phenomenon'), getValues('locationIndicatorATSR'), productConfig)} hours after Valid from time`
4890
+ isXHoursAfter: value => isXHoursAfter(value, getValues('validDateStart'), getMaxHoursOfValidity(getValues('phenomenon'), getValues('locationIndicatorATSR'), productConfig)) || t('valid-until-time-error', {
4891
+ hours: getMaxHoursOfValidity(getValues('phenomenon'), getValues('locationIndicatorATSR'), productConfig)
4892
+ })
4318
4893
  }
4319
4894
  },
4320
4895
  disabled: isDisabled,
@@ -4333,6 +4908,9 @@ const VolcanicFields = ({
4333
4908
  isReadOnly,
4334
4909
  helperText
4335
4910
  }) => {
4911
+ const {
4912
+ t
4913
+ } = useSigmetAirmetTranslation();
4336
4914
  const {
4337
4915
  watch,
4338
4916
  trigger,
@@ -4361,7 +4939,7 @@ const VolcanicFields = ({
4361
4939
  }, {
4362
4940
  children: jsx(ReactHookFormTextField, {
4363
4941
  name: "vaSigmetVolcanoName",
4364
- label: "Volcano name",
4942
+ label: t('volcano-name'),
4365
4943
  rules: {
4366
4944
  required: false
4367
4945
  },
@@ -4378,7 +4956,7 @@ const VolcanicFields = ({
4378
4956
  children: jsx(ReactHookFormNumberField, {
4379
4957
  name: "vaSigmetVolcanoCoordinates.latitude",
4380
4958
  "data-testid": "vaSigmetVolcanoCoordinates.latitude",
4381
- label: "Latitude",
4959
+ label: t('latitude'),
4382
4960
  inputMode: "decimal",
4383
4961
  rules: {
4384
4962
  required: true,
@@ -4400,7 +4978,7 @@ const VolcanicFields = ({
4400
4978
  children: jsx(ReactHookFormNumberField, {
4401
4979
  name: "vaSigmetVolcanoCoordinates.longitude",
4402
4980
  "data-testid": "vaSigmetVolcanoCoordinates.longitude",
4403
- label: "Longitude",
4981
+ label: t('longitude'),
4404
4982
  inputMode: "decimal",
4405
4983
  size: "small",
4406
4984
  sx: Object.assign({}, styles$2.latitude),
@@ -4422,8 +5000,12 @@ const VolcanicFields = ({
4422
5000
 
4423
5001
  const DEFAULT_ROUNDING_SURFACE_VISIBLILITY_BELOW = 50;
4424
5002
  const DEFAULT_ROUNDING_SURFACE_VISIBLILITY_ABOVE = 100;
4425
- const getInvalidSurfaceVisibilityTill750StepsMessage = (value = DEFAULT_ROUNDING_SURFACE_VISIBLILITY_BELOW) => `A visibility below 750m must be rounded to the nearest ${value}m`;
4426
- const getInvalidSurfaceVisibilityFrom750StepsMessage = (value = DEFAULT_ROUNDING_SURFACE_VISIBLILITY_ABOVE) => `A visibility above 750m must be rounded to the nearest ${value}m`;
5003
+ const getInvalidSurfaceVisibilityTill750StepsMessage = (value = DEFAULT_ROUNDING_SURFACE_VISIBLILITY_BELOW) => translateKeyOutsideComponents('invalid-surface-visibility-till-750-steps-message', {
5004
+ value
5005
+ });
5006
+ const getInvalidSurfaceVisibilityFrom750StepsMessage = (value = DEFAULT_ROUNDING_SURFACE_VISIBLILITY_ABOVE) => translateKeyOutsideComponents('invalid-surface-visibility-from-750-steps-message', {
5007
+ value
5008
+ });
4427
5009
  const validateSurfaceVisibility = (value, productConfig, selectedFIR) => {
4428
5010
  if (isEmpty(value)) {
4429
5011
  return true;
@@ -4447,6 +5029,9 @@ const SurfaceVisibility = ({
4447
5029
  productConfig,
4448
5030
  onChange: _onChange = () => {}
4449
5031
  }) => {
5032
+ const {
5033
+ t
5034
+ } = useSigmetAirmetTranslation();
4450
5035
  const {
4451
5036
  isRequired
4452
5037
  } = useDraftFormHelpers();
@@ -4454,8 +5039,8 @@ const SurfaceVisibility = ({
4454
5039
  getValues
4455
5040
  } = useFormContext();
4456
5041
  const getFIRValue = () => getValues('locationIndicatorATSR');
4457
- const visibilityLabel = getFieldLabel('Visibility', isReadOnly);
4458
- const visibilityCauseLabel = getFieldLabel('Cause', isReadOnly);
5042
+ const visibilityLabel = getFieldLabel(t('surface-visibility'), isReadOnly);
5043
+ const visibilityCauseLabel = getFieldLabel(t('surface-visibility-cause'), isReadOnly);
4459
5044
  return jsxs(Grid, Object.assign({
4460
5045
  item: true,
4461
5046
  container: true,
@@ -4481,16 +5066,20 @@ const SurfaceVisibility = ({
4481
5066
  name: "visibilityValue",
4482
5067
  "data-testid": "surfaceVisibility-visibilityValue",
4483
5068
  label: visibilityLabel,
4484
- helperText: "Value in meters",
5069
+ helperText: t('surface-visibility-helper-text'),
4485
5070
  rules: {
4486
5071
  validate: {
4487
5072
  isRequired,
4488
5073
  min: value =>
4489
5074
  // The min level depends on the unit
4490
- isValidMin(value, getMinVisibilityValue(getFIRValue(), productConfig)) || `The minimum visibility in meters is ${getMinVisibilityValue(getFIRValue(), productConfig)}`,
5075
+ isValidMin(value, getMinVisibilityValue(getFIRValue(), productConfig)) || t('surface-visibility-minimum-visibility', {
5076
+ minimumVisibility: getMinVisibilityValue(getFIRValue(), productConfig)
5077
+ }),
4491
5078
  max: value =>
4492
5079
  // The max level depends on the unit
4493
- isValidMax(value, getMaxVisibilityValue(getFIRValue(), productConfig)) || `The maximum visibility in meters is ${getMaxVisibilityValue(getFIRValue(), productConfig)}`,
5080
+ isValidMax(value, getMaxVisibilityValue(getFIRValue(), productConfig)) || t('surface-visibility-maximum-visibility', {
5081
+ maximumVisibility: getMaxVisibilityValue(getFIRValue(), productConfig)
5082
+ }),
4494
5083
  validateSurfaceVisibility: value => validateSurfaceVisibility(value, productConfig, getFIRValue())
4495
5084
  }
4496
5085
  },
@@ -4531,7 +5120,9 @@ const SurfaceVisibility = ({
4531
5120
  };
4532
5121
 
4533
5122
  const DEFAULT_ROUNDING_SURFACE_WIND_DIRECTION = 10;
4534
- const invalidSurfaceWindDirectionStepsMessage = (value = DEFAULT_ROUNDING_SURFACE_WIND_DIRECTION) => `Direction must be rounded to the nearest ${value} deg.`;
5123
+ const invalidSurfaceWindDirectionStepsMessage = (value = DEFAULT_ROUNDING_SURFACE_WIND_DIRECTION) => translateKeyOutsideComponents('invalid-surface-wind-direction-message', {
5124
+ value
5125
+ });
4535
5126
  const validateSurfaceWindDirection = (value, productConfig, selectedFIR) => {
4536
5127
  if (isEmpty(value)) {
4537
5128
  return true;
@@ -4550,6 +5141,9 @@ const SurfaceWind = ({
4550
5141
  onChange: _onChange = () => null,
4551
5142
  productConfig
4552
5143
  }) => {
5144
+ const {
5145
+ t
5146
+ } = useSigmetAirmetTranslation();
4553
5147
  const {
4554
5148
  trigger,
4555
5149
  getValues
@@ -4560,8 +5154,8 @@ const SurfaceWind = ({
4560
5154
  const getFIRValue = () => getValues('locationIndicatorATSR');
4561
5155
  // Get allowed speed units based on selected FIR - if no FIR selected, allow all units
4562
5156
  const allowedWindUnitsForFir = getAllowedUnits(getFIRValue(), productConfig, 'surfacewind_unit', WindUnit);
4563
- const windLabel = getFieldLabel('Wind direction', isReadOnly, 'Set');
4564
- const speedLabel = getFieldLabel('Speed', isReadOnly, 'Set');
5157
+ const windLabel = getFieldLabel(t('surface-wind-label'), isReadOnly, t('set'));
5158
+ const speedLabel = getFieldLabel(t('surface-wind-speed-label'), isReadOnly, t('set'));
4565
5159
  return jsxs(Grid, Object.assign({
4566
5160
  item: true,
4567
5161
  container: true,
@@ -4586,15 +5180,15 @@ const SurfaceWind = ({
4586
5180
  children: jsx(ReactHookFormNumberField, {
4587
5181
  name: "windDirection",
4588
5182
  label: windLabel,
4589
- helperText: "Value in degrees",
5183
+ helperText: t('surface-wind-helper-text'),
4590
5184
  rules: {
4591
5185
  min: {
4592
5186
  value: 10,
4593
- message: 'Direction should be between 10 and 360 deg.'
5187
+ message: t('surface-wind-rule-min-max-message')
4594
5188
  },
4595
5189
  max: {
4596
5190
  value: 360,
4597
- message: 'Direction should be between 10 and 360 deg.'
5191
+ message: t('surface-wind-rule-min-max-message')
4598
5192
  },
4599
5193
  validate: {
4600
5194
  isRequired,
@@ -4617,7 +5211,7 @@ const SurfaceWind = ({
4617
5211
  }, {
4618
5212
  children: jsx(ReactHookFormSelect, Object.assign({
4619
5213
  name: "windUnit",
4620
- label: "Unit",
5214
+ label: t('unit-label'),
4621
5215
  rules: {
4622
5216
  validate: {
4623
5217
  isRequired
@@ -4653,10 +5247,16 @@ const SurfaceWind = ({
4653
5247
  isInteger,
4654
5248
  min: value =>
4655
5249
  // The min level depends on the unit
4656
- isValidMin(value, getMinWindSpeedValue(getValues('windUnit'), getFIRValue(), productConfig)) || `The minimum wind speed in ${WindUnit[getValues('windUnit')]} is ${getMinWindSpeedValue(getValues('windUnit'), getFIRValue(), productConfig)}`,
5250
+ isValidMin(value, getMinWindSpeedValue(getValues('windUnit'), getFIRValue(), productConfig)) || t('surface-wind-minimum-wind-speed', {
5251
+ windUnit: WindUnit[getValues('windUnit')],
5252
+ minWindSpeedValue: getMinWindSpeedValue(getValues('windUnit'), getFIRValue(), productConfig)
5253
+ }),
4657
5254
  max: value =>
4658
5255
  // The max level depends on the unit
4659
- isValidMax(value, getMaxWindSpeedValue(getValues('windUnit'), getFIRValue(), productConfig)) || `The maximum wind speed in ${WindUnit[getValues('windUnit')]} is ${getMaxWindSpeedValue(getValues('windUnit'), getFIRValue(), productConfig)}`
5256
+ isValidMax(value, getMaxWindSpeedValue(getValues('windUnit'), getFIRValue(), productConfig)) || t('surface-wind-maximum-wind-speed', {
5257
+ windUnit: WindUnit[getValues('windUnit')],
5258
+ maxWindSpeedValue: getMaxWindSpeedValue(getValues('windUnit'), getFIRValue(), productConfig)
5259
+ })
4660
5260
  }
4661
5261
  },
4662
5262
  size: "small",
@@ -4715,6 +5315,9 @@ const CloudLevels = ({
4715
5315
  const {
4716
5316
  isRequired
4717
5317
  } = useDraftFormHelpers();
5318
+ const {
5319
+ t
5320
+ } = useSigmetAirmetTranslation();
4718
5321
  const getFIRValue = () => getValues('locationIndicatorATSR');
4719
5322
  const cloudLevelInfoMode = watch('cloudLevelInfoMode');
4720
5323
  // Get allowed cloud level units based on selected FIR - if no FIR selected, allow all default units
@@ -4740,7 +5343,7 @@ const CloudLevels = ({
4740
5343
  variant: "subtitle1",
4741
5344
  sx: styles$2.label
4742
5345
  }, {
4743
- children: "Levels"
5346
+ children: t('levels')
4744
5347
  }))
4745
5348
  })), jsx(Grid, Object.assign({
4746
5349
  item: true,
@@ -4980,7 +5583,8 @@ const CloudLevels = ({
4980
5583
  }));
4981
5584
  };
4982
5585
 
4983
- const noTAC = 'Missing data: no TAC can be generated';
5586
+ // ToDo check if this can be transated here
5587
+ const noTAC = translateKeyOutsideComponents('tac-missing-data');
4984
5588
  const isLevelFieldsComplete = product => {
4985
5589
  var _a, _b, _c, _d, _e, _f;
4986
5590
  switch (product.phenomenon) {
@@ -5054,6 +5658,10 @@ const shouldRetrieveTAC = (product, omitChange) => {
5054
5658
  return false;
5055
5659
  };
5056
5660
  const useTAC = (initialProduct, getTAC, hasErrors = () => false, omitChange) => {
5661
+ const {
5662
+ t
5663
+ } = useSigmetAirmetTranslation();
5664
+ const noTAC = t('tac-missing-data');
5057
5665
  const [TAC, setTAC] = React__default.useState(noTAC);
5058
5666
  const {
5059
5667
  isMounted
@@ -5128,6 +5736,9 @@ const IssuedAt = ({
5128
5736
  date,
5129
5737
  isReadOnly
5130
5738
  }) => {
5739
+ const {
5740
+ t
5741
+ } = useSigmetAirmetTranslation();
5131
5742
  return jsx(ProductFormFieldLayout, Object.assign({
5132
5743
  sx: {
5133
5744
  paddingTop: 0,
@@ -5135,7 +5746,7 @@ const IssuedAt = ({
5135
5746
  paddingTop: 0
5136
5747
  }
5137
5748
  },
5138
- title: "Issued at"
5749
+ title: t('issued-at')
5139
5750
  }, {
5140
5751
  children: jsx(Grid, Object.assign({
5141
5752
  item: true,
@@ -9390,6 +10001,9 @@ const SigmetForm = ({
9390
10001
  productConfig: _productConfig = sigmetConfig,
9391
10002
  setDialogActionsDisabled
9392
10003
  }) => {
10004
+ const {
10005
+ t
10006
+ } = useSigmetAirmetTranslation();
9393
10007
  const {
9394
10008
  api
9395
10009
  } = useApiContext();
@@ -9625,7 +10239,7 @@ const SigmetForm = ({
9625
10239
  sx: styles$2.body,
9626
10240
  "data-testid": "vaSigmetMoveToFIR"
9627
10241
  }, {
9628
- children: ["Volcanic Cloud is moving in the direction of:", ' ', jsxs("b", {
10242
+ children: [t('vulcanic-cloud-moving-text'), ":", ' ', jsxs("b", {
9629
10243
  children: [" ", watch('vaSigmetMoveToFIR')]
9630
10244
  })]
9631
10245
  }))
@@ -9954,6 +10568,9 @@ const ContentDialog = _a => {
9954
10568
  alertBanner = null
9955
10569
  } = _a,
9956
10570
  other = __rest(_a, ["open", "toggleDialogStatus", "title", "children", "options", "onClose", "alertBanner"]);
10571
+ const {
10572
+ t
10573
+ } = useSigmetAirmetTranslation();
9957
10574
  const theme = useTheme();
9958
10575
  const handleClose = () => {
9959
10576
  if (onClose) {
@@ -10021,7 +10638,7 @@ const ContentDialog = _a => {
10021
10638
  }
10022
10639
  }
10023
10640
  }, {
10024
- children: "BACK"
10641
+ children: t('back')
10025
10642
  }))
10026
10643
  })), jsx(Grid, Object.assign({
10027
10644
  item: true,
@@ -10221,6 +10838,9 @@ const ProductListRow = ({
10221
10838
  product,
10222
10839
  productType
10223
10840
  }) => {
10841
+ const {
10842
+ t
10843
+ } = useSigmetAirmetTranslation();
10224
10844
  const {
10225
10845
  api
10226
10846
  } = useApiContext();
@@ -10311,7 +10931,7 @@ const ProductListRow = ({
10311
10931
  item: true
10312
10932
  }, {
10313
10933
  children: [jsx(ProductListRowHeader, {
10314
- title: "Issue time"
10934
+ title: t('issue-time')
10315
10935
  }), jsx(CustomTooltip, Object.assign({
10316
10936
  title: jsxs(Fragment, {
10317
10937
  children: [jsx(ProductListRowHeader, {
@@ -10352,7 +10972,7 @@ const ProductListRow = ({
10352
10972
  sx: styles.font,
10353
10973
  "data-testid": "issueTime"
10354
10974
  }, {
10355
- children: product.issueDate ? `${dateUtils.dateToString(dateUtils.utc(product.issueDate), dateUtils.DATE_FORMAT_NAME_OF_MONTH)} UTC` : '(Not published)'
10975
+ children: product.issueDate ? `${dateUtils.dateToString(dateUtils.utc(product.issueDate), dateUtils.DATE_FORMAT_NAME_OF_MONTH)} UTC` : t('not-published')
10356
10976
  }))
10357
10977
  }))]
10358
10978
  })), jsxs(Grid, Object.assign({
@@ -10360,7 +10980,7 @@ const ProductListRow = ({
10360
10980
  item: true
10361
10981
  }, {
10362
10982
  children: [jsx(ProductListRowHeader, {
10363
- title: "Valid time"
10983
+ title: t('valid-time')
10364
10984
  }), jsx(Typography, Object.assign({
10365
10985
  variant: "subtitle2",
10366
10986
  sx: styles.font,
@@ -10380,7 +11000,7 @@ const ProductListRow = ({
10380
11000
  variant: "flat",
10381
11001
  startIcon: jsx(Edit, {})
10382
11002
  }, {
10383
- children: "DRAFT"
11003
+ children: t('draft')
10384
11004
  })) : getStatusTagList(product, cancelsSeqId), product.status === 'PUBLISHED' && cancelsSeqId === null && getActiveStatus(product)]
10385
11005
  }))]
10386
11006
  }))
@@ -10388,97 +11008,6 @@ const ProductListRow = ({
10388
11008
  }));
10389
11009
  };
10390
11010
 
10391
- const ERROR_CONFIG = 'An error has occurred while loading the config';
10392
- const ERROR_BACKEND = 'An error has occurred while retrieving the list, please try again';
10393
- const ERROR_AUTH$1 = 'This feature is protected by authentication.';
10394
- const validateConfig = (productType, productConfig) => {
10395
- const validatedConfig = productType === 'sigmet' ? validateSigmet(productConfig) : validateAirmet(productConfig);
10396
- if (validatedConfig !== true && Array.isArray(validatedConfig)) {
10397
- const error = {
10398
- name: ERROR_CONFIG,
10399
- message: createReadableErrorMessage(validatedConfig)
10400
- };
10401
- return error;
10402
- }
10403
- return true;
10404
- };
10405
- const useProductApi = (productType, productConfig) => {
10406
- const [state, setState] = React__default.useState({
10407
- isLoading: false,
10408
- error: undefined,
10409
- result: []
10410
- });
10411
- const {
10412
- isMounted
10413
- } = useIsMounted();
10414
- const {
10415
- api
10416
- } = useApiContext();
10417
- const requestList = productType === 'sigmet' ? api.getSigmetList : api.getAirmetList;
10418
- const {
10419
- isLoggedIn
10420
- } = useAuthenticationContext();
10421
- const updateState = newState => {
10422
- if (isMounted.current) {
10423
- setState(currentState => Object.assign(Object.assign({}, currentState), newState));
10424
- }
10425
- };
10426
- const fetchNewData = () => __awaiter(void 0, void 0, void 0, function* () {
10427
- var _a;
10428
- // Check for authentication before fetching data
10429
- if (!isLoggedIn && Array.isArray(isLoggedIn)) {
10430
- const newError = {
10431
- name: ERROR_AUTH$1,
10432
- message: createReadableErrorMessage(isLoggedIn)
10433
- };
10434
- updateState(Object.assign(Object.assign({}, state), {
10435
- error: newError,
10436
- isLoading: false
10437
- }));
10438
- return;
10439
- }
10440
- // don't try to fetch when error coming from config or is loading already
10441
- if (((_a = state.error) === null || _a === void 0 ? void 0 : _a.name) === ERROR_CONFIG || state.isLoading) {
10442
- return;
10443
- }
10444
- updateState(Object.assign(Object.assign({}, state), {
10445
- isLoading: true,
10446
- error: undefined
10447
- }));
10448
- try {
10449
- const {
10450
- data
10451
- } = yield requestList();
10452
- updateState(Object.assign(Object.assign({}, state), {
10453
- result: data,
10454
- isLoading: false
10455
- }));
10456
- } catch (error) {
10457
- const newError = Object.assign(Object.assign({}, error), {
10458
- name: ERROR_BACKEND
10459
- });
10460
- updateState(Object.assign(Object.assign({}, state), {
10461
- error: newError,
10462
- isLoading: false
10463
- }));
10464
- }
10465
- });
10466
- React__default.useEffect(() => {
10467
- const validatedConfig = validateConfig(productType, productConfig);
10468
- if (validatedConfig !== true) {
10469
- updateState(Object.assign(Object.assign({}, state), {
10470
- error: validatedConfig
10471
- }));
10472
- } else {
10473
- fetchNewData();
10474
- }
10475
- // eslint-disable-next-line react-hooks/exhaustive-deps
10476
- }, []);
10477
- return Object.assign(Object.assign({}, state), {
10478
- fetchNewData
10479
- });
10480
- };
10481
-
10482
11011
  const ProductList = ({
10483
11012
  productType,
10484
11013
  productList,
@@ -10487,7 +11016,10 @@ const ProductList = ({
10487
11016
  onClickProductRow,
10488
11017
  onClickNewProduct
10489
11018
  }) => {
10490
- const shouldHideCreateNew = error && (error.name === ERROR_AUTH$1 || error.name === ERROR_CONFIG);
11019
+ const {
11020
+ t
11021
+ } = useSigmetAirmetTranslation();
11022
+ const shouldHideCreateNew = error && (error.name === t('error-auth') || error.name === t('error-config'));
10491
11023
  return jsxs(Grid, Object.assign({
10492
11024
  container: true,
10493
11025
  direction: "column",
@@ -10498,7 +11030,7 @@ const ProductList = ({
10498
11030
  item: true,
10499
11031
  justifyContent: "flex-end"
10500
11032
  }, {
10501
- children: !shouldHideCreateNew && jsxs(Button, Object.assign({
11033
+ children: !shouldHideCreateNew && jsx(Button, Object.assign({
10502
11034
  variant: "primary",
10503
11035
  "data-testid": "productListCreateButton",
10504
11036
  onClick: onClickNewProduct,
@@ -10506,7 +11038,9 @@ const ProductList = ({
10506
11038
  textTransform: 'initial'
10507
11039
  }
10508
11040
  }, {
10509
- children: ["Create a new ", productType.toUpperCase()]
11041
+ children: t('create-new-product', {
11042
+ product: productType.toUpperCase()
11043
+ })
10510
11044
  }))
10511
11045
  })), jsxs(Grid, Object.assign({
10512
11046
  item: true,
@@ -10563,14 +11097,17 @@ const CancelSigmetVolcanicMovements = ({
10563
11097
  productConfig
10564
11098
  }) => {
10565
11099
  const allFIRS = getAllFirAreas(productConfig);
11100
+ const {
11101
+ t
11102
+ } = useSigmetAirmetTranslation();
10566
11103
  const {
10567
11104
  isRequired
10568
11105
  } = useDraftFormHelpers();
10569
11106
  return jsxs(Fragment, {
10570
- children: [jsx(Typography, Object.assign({
11107
+ children: [jsxs(Typography, Object.assign({
10571
11108
  variant: "body1"
10572
11109
  }, {
10573
- children: "Use the FIR to indicate the direction the Volcanic Ash is moving to:"
11110
+ children: [t('vulcanic-ash-description'), ":"]
10574
11111
  })), jsxs(ReactHookFormRadioGroup, Object.assign({
10575
11112
  name: "vaSigmetMoveToFIR",
10576
11113
  rules: {
@@ -10579,7 +11116,7 @@ const CancelSigmetVolcanicMovements = ({
10579
11116
  }
10580
11117
  },
10581
11118
  row: true,
10582
- defaultValue: "UNKNOWN"
11119
+ defaultValue: t('unknown').toUpperCase()
10583
11120
  }, {
10584
11121
  children: [allFIRS[sigmet.locationIndicatorATSR].adjacent_firs.map(adjacentFIR => {
10585
11122
  return jsx(FormControlLabel, {
@@ -10590,7 +11127,7 @@ const CancelSigmetVolcanicMovements = ({
10590
11127
  }), jsx(FormControlLabel, {
10591
11128
  value: "UNKNOWN",
10592
11129
  control: jsx(Radio, {}),
10593
- label: "Cancel VA SIGMET without VA MOV TO information"
11130
+ label: t('vulcanic-VA-SIGMET-text')
10594
11131
  }, "UNKNOWN")]
10595
11132
  }))]
10596
11133
  });
@@ -10837,6 +11374,94 @@ const ProductFormDialog = ({
10837
11374
  });
10838
11375
  };
10839
11376
 
11377
+ const validateConfig = (productType, productConfig) => {
11378
+ const validatedConfig = productType === 'sigmet' ? validateSigmet(productConfig) : validateAirmet(productConfig);
11379
+ if (validatedConfig !== true && Array.isArray(validatedConfig)) {
11380
+ const error = {
11381
+ name: translateKeyOutsideComponents('error-config'),
11382
+ message: createReadableErrorMessage(validatedConfig)
11383
+ };
11384
+ return error;
11385
+ }
11386
+ return true;
11387
+ };
11388
+ const useProductApi = (productType, productConfig) => {
11389
+ const [state, setState] = React__default.useState({
11390
+ isLoading: false,
11391
+ error: undefined,
11392
+ result: []
11393
+ });
11394
+ const {
11395
+ isMounted
11396
+ } = useIsMounted();
11397
+ const {
11398
+ api
11399
+ } = useApiContext();
11400
+ const requestList = productType === 'sigmet' ? api.getSigmetList : api.getAirmetList;
11401
+ const {
11402
+ isLoggedIn
11403
+ } = useAuthenticationContext();
11404
+ const updateState = newState => {
11405
+ if (isMounted.current) {
11406
+ setState(currentState => Object.assign(Object.assign({}, currentState), newState));
11407
+ }
11408
+ };
11409
+ const fetchNewData = () => __awaiter(void 0, void 0, void 0, function* () {
11410
+ var _a;
11411
+ // Check for authentication before fetching data
11412
+ if (!isLoggedIn && Array.isArray(isLoggedIn)) {
11413
+ const newError = {
11414
+ name: translateKeyOutsideComponents('error-auth'),
11415
+ message: createReadableErrorMessage(isLoggedIn)
11416
+ };
11417
+ updateState(Object.assign(Object.assign({}, state), {
11418
+ error: newError,
11419
+ isLoading: false
11420
+ }));
11421
+ return;
11422
+ }
11423
+ // don't try to fetch when error coming from config or is loading already
11424
+ if (((_a = state.error) === null || _a === void 0 ? void 0 : _a.name) === translateKeyOutsideComponents('error-config') || state.isLoading) {
11425
+ return;
11426
+ }
11427
+ updateState(Object.assign(Object.assign({}, state), {
11428
+ isLoading: true,
11429
+ error: undefined
11430
+ }));
11431
+ try {
11432
+ const {
11433
+ data
11434
+ } = yield requestList();
11435
+ updateState(Object.assign(Object.assign({}, state), {
11436
+ result: data,
11437
+ isLoading: false
11438
+ }));
11439
+ } catch (error) {
11440
+ const newError = Object.assign(Object.assign({}, error), {
11441
+ name: translateKeyOutsideComponents('error-backend')
11442
+ });
11443
+ updateState(Object.assign(Object.assign({}, state), {
11444
+ error: newError,
11445
+ isLoading: false
11446
+ }));
11447
+ }
11448
+ });
11449
+ React__default.useEffect(() => {
11450
+ const validatedConfig = validateConfig(productType, productConfig);
11451
+ if (validatedConfig !== true) {
11452
+ updateState(Object.assign(Object.assign({}, state), {
11453
+ error: validatedConfig
11454
+ }));
11455
+ } else {
11456
+ fetchNewData();
11457
+ }
11458
+ // eslint-disable-next-line react-hooks/exhaustive-deps
11459
+ }, []);
11460
+ return Object.assign(Object.assign({}, state), {
11461
+ fetchNewData
11462
+ });
11463
+ };
11464
+
10840
11465
  /**
10841
11466
  * Shows the list of Sigmets or Airmets and allows to create, edit and view Sigmets/Airmets.
10842
11467
  * Needs to be wrapped in the ApiProvider.
@@ -10909,12 +11534,13 @@ const MetInfoWrapper = ({
10909
11534
  }));
10910
11535
  };
10911
11536
 
10912
- const ERROR_TITLE = 'Something went wrong with loading the configuration file';
10913
- const ERROR_AUTH = 'This feature is protected by authentication. Please log in to proceed';
10914
11537
  const DownloadSigmetAirmetConfigWrapper = ({
10915
11538
  productType,
10916
11539
  productConfigKey
10917
11540
  }) => {
11541
+ const {
11542
+ t
11543
+ } = useSigmetAirmetTranslation();
10918
11544
  const {
10919
11545
  api
10920
11546
  } = useApiContext();
@@ -10942,8 +11568,8 @@ const DownloadSigmetAirmetConfigWrapper = ({
10942
11568
  }
10943
11569
  if (error) {
10944
11570
  return jsx(AlertBanner, {
10945
- title: ERROR_TITLE,
10946
- info: !isLoggedIn ? ERROR_AUTH : error.message
11571
+ title: t('error-title'),
11572
+ info: !isLoggedIn ? t('error-auth-login') : error.message
10947
11573
  });
10948
11574
  }
10949
11575
  return jsx(MetInfoWrapper, {
@@ -14596,6 +15222,4 @@ ConnectedModuleWrapper = null) => {
14596
15222
  }
14597
15223
  };
14598
15224
 
14599
- const SA_NAMESPACE = 'sigmetairmet';
14600
-
14601
15225
  export { AirmetComponentsLookUp, AirmetForm, AirmetPhenomena, AirmetType, CloudLevelUnits, ContentDialog, Direction, DownloadSigmetAirmetConfigWrapper, LevelUnits, MapViewGeoJson, MetInfoWrapper, MovementUnit, ProductList, ProductListRow, ProductStatusDescription, SA_NAMESPACE, SigmetComponentsLookUp, SigmetForm, SigmetPhenomena, SigmetType, StartOrEndDrawing, VisibilityCause, WindUnit, airmetConfig, createApi$1 as createApi, createApi as createFakeApi, isInstanceOfAirmet, isInstanceOfCancelAirmet, isInstanceOfCancelSigmet, isInstanceOfCancelSigmetOrAirmet, isInstanceOfSigmet, isInstanceOfSigmetOrAirmet, sigmetAirmetTranslations as saTranslations, sigmetConfig };