@govuk-one-login/frontend-ui 1.0.2 → 1.2.0
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/README.md +33 -7
- package/build/all.css +1 -1
- package/build/cjs/index-fe.cjs +122 -0
- package/build/cjs/index.cjs +44 -8
- package/build/cjs/index.d.cts +38 -0
- package/build/cjs/index.d.ts +25 -16
- package/build/cjs/index.d.ts.map +1 -1
- package/build/components/_all.scss +2 -0
- package/build/components/bases/auth/auth-base.njk +137 -0
- package/build/components/bases/home/home-base.njk +135 -0
- package/build/components/bases/identity/identity-base-form.njk +14 -1
- package/build/components/bases/identity/identity-base-page.njk +11 -4
- package/build/components/bases/ipv-core/ipv-core-base.njk +154 -0
- package/build/components/bases/mobile/mobile-base.njk +129 -0
- package/build/components/cookie-banner/template.njk +1 -1
- package/build/components/footer/_index.scss +8 -0
- package/build/components/footer/template.njk +7 -4
- package/build/components/header/_index.scss +54 -0
- package/build/components/header/template.njk +36 -85
- package/build/components/macros/logo.njk +75 -0
- package/build/components/phase-banner/_index.scss +16 -16
- package/build/components/phase-banner/template.njk +4 -0
- package/build/components/spinner/README.md +107 -0
- package/build/components/spinner/_index.scss +64 -0
- package/build/components/spinner/api.njk +27 -0
- package/build/components/spinner/javascript/spinner.js +118 -0
- package/build/components/spinner/macro.njk +3 -0
- package/build/components/spinner/template.njk +11 -0
- package/build/esm/index-fe.js +120 -0
- package/build/esm/index.d.ts +25 -16
- package/build/esm/index.d.ts.map +1 -1
- package/build/esm/index.js +43 -9
- package/build/frontendUiAssets/images/favicon.ico +0 -0
- package/build/frontendUiAssets/images/favicon.svg +1 -0
- package/build/frontendUiAssets/images/govuk-crest.svg +1 -0
- package/build/frontendUiAssets/images/govuk-icon-180.png +0 -0
- package/build/frontendUiAssets/images/govuk-icon-192.png +0 -0
- package/build/frontendUiAssets/images/govuk-icon-512.png +0 -0
- package/build/frontendUiAssets/images/govuk-icon-mask.svg +1 -0
- package/build/frontendUiAssets/images/govuk-opengraph-image.png +0 -0
- package/package.json +15 -5
package/README.md
CHANGED
|
@@ -27,7 +27,7 @@ app.set(
|
|
|
27
27
|
'view engine',
|
|
28
28
|
configureNunjucks(app, [
|
|
29
29
|
// ... other view paths ...
|
|
30
|
-
path.resolve('node_modules/@govuk-one-login/frontend-ui')
|
|
30
|
+
path.resolve('node_modules/@govuk-one-login/frontend-ui')
|
|
31
31
|
]),
|
|
32
32
|
);
|
|
33
33
|
```
|
|
@@ -44,20 +44,25 @@ const frontendUi = require("@govuk-one-login/frontend-ui");
|
|
|
44
44
|
|
|
45
45
|
nunjucksEnv.addGlobal("addLanguageParam", frontendUi.addLanguageParam);
|
|
46
46
|
nunjucksEnv.addGlobal("contactUsUrl", frontendUi.contactUsUrl);
|
|
47
|
+
nunjucksEnv.addGlobal("May_2025_Rebrand", process.env.May_2025_Rebrand == "true");
|
|
47
48
|
```
|
|
48
49
|
Typescript:
|
|
49
50
|
```typescript
|
|
50
51
|
import {contactUsUrl, addLanguageParam } from "@govuk-one-login/frontend-ui";
|
|
51
52
|
nunjucksEnv.addGlobal("addLanguageParam", addLanguageParam);
|
|
52
53
|
nunjucksEnv.addGlobal("contactUsUrl", contactUsUrl);
|
|
54
|
+
nunjucksEnv.addGlobal("May_2025_Rebrand", process.env.May_2025_Rebrand == "true");
|
|
53
55
|
```
|
|
54
56
|
|
|
57
|
+
In order to use the `May_2025_Rebrand` variable you will need to create or add to your `.env` file the following `May_2025_Rebrand=`[true/false]
|
|
58
|
+
|
|
55
59
|
### 4. Load Translations and Configure Middleware
|
|
56
60
|
|
|
57
61
|
In your `app.js`, import necessary functions and load translations after initializing i18next (Identity teams may need to use the bypass function as their i18n setup is different):
|
|
58
62
|
|
|
59
63
|
```javascript
|
|
60
64
|
const {
|
|
65
|
+
setBaseTranslations
|
|
61
66
|
setFrontendUiTranslations,
|
|
62
67
|
frontendUiMiddleware,
|
|
63
68
|
} = require('@govuk-one-login/frontend-ui');
|
|
@@ -74,8 +79,6 @@ i18next
|
|
|
74
79
|
),
|
|
75
80
|
},
|
|
76
81
|
(err) => {
|
|
77
|
-
// Load Frontend UI translations after i18next initialization and pass current instance of i18next
|
|
78
|
-
setFrontendUiTranslations(i18next);
|
|
79
82
|
|
|
80
83
|
if (err) {
|
|
81
84
|
console.error('i18next init failed:', err);
|
|
@@ -84,6 +87,9 @@ i18next
|
|
|
84
87
|
);
|
|
85
88
|
|
|
86
89
|
// Apply the middleware
|
|
90
|
+
setBaseTranslations(i18next);
|
|
91
|
+
setFrontendUiTranslations(i18next);
|
|
92
|
+
app.use(i18nextMiddleware.handle(i18next));
|
|
87
93
|
app.use(frontendUiMiddleware);
|
|
88
94
|
|
|
89
95
|
// For Identity teams a language setting bypass may be required, first import the bypass function and then configure router to use the new function at the top of your router.use functions
|
|
@@ -116,19 +122,39 @@ or
|
|
|
116
122
|
```
|
|
117
123
|
|
|
118
124
|
### 6. Import all.css
|
|
119
|
-
Import the css into your service in the `package.json` via the `build-sass` script
|
|
125
|
+
Import the css into your service in the `package.json` via the `build-sass` script.
|
|
126
|
+
```
|
|
127
|
+
sass --no-source-map ../../node_modules/@govuk-one-login/frontend-ui/build/all.css [WhereYouStoreStyleSheets]/frontendUi.css --style compressed"
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
You will also need to add the following in order to ensure that the assets all load properly across the basefiles
|
|
120
131
|
```
|
|
121
|
-
|
|
132
|
+
"cp -R ../../node_modules/@govuk-one-login/frontend-ui/build/frontendUiAssets [OneLevelAboveWhereYouStoreStyleSheets/SameFolderAsStyleSheets]/"
|
|
122
133
|
```
|
|
123
134
|
|
|
124
|
-
include a link to this in your template file
|
|
135
|
+
include a link to this in your template file, this has been done in the created basefiles already
|
|
125
136
|
```html
|
|
126
137
|
{% block head %}
|
|
127
138
|
'''
|
|
128
|
-
|
|
139
|
+
<link rel="stylesheet" href="/[WhereYouStoreStyleSheets]/frontendUi.css"/>
|
|
129
140
|
{% endblock %}
|
|
130
141
|
```
|
|
131
142
|
|
|
143
|
+
Or alternatively you can import the frontend-ui all.css directly into your exisiting css file if you are having a 'flickering' issue
|
|
144
|
+
``` scss
|
|
145
|
+
$govuk-assets-path: "/public/";
|
|
146
|
+
$hmpo-summary-list: false;
|
|
147
|
+
|
|
148
|
+
@import "../../../node_modules/govuk-frontend/govuk/all";
|
|
149
|
+
@import "../../../node_modules/hmpo-components/all";
|
|
150
|
+
@import "../../../node_modules/@govuk-one-login/frontend-language-toggle/stylesheet/styles";
|
|
151
|
+
@import "../../../node_modules/accessible-autocomplete/dist/accessible-autocomplete.min";
|
|
152
|
+
@import "components/button-spinner";
|
|
153
|
+
@import "components/country-picker";
|
|
154
|
+
|
|
155
|
+
@import "../../../node_modules/@govuk-one-login/frontend-ui/build/all.css"; // <--- HERE>
|
|
156
|
+
|
|
157
|
+
```
|
|
132
158
|
|
|
133
159
|
### 7. Add Component to Template
|
|
134
160
|
|
package/build/all.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
@media(max-width: 640px){.govuk-header__navigation-item{border-left:none !important}}.frontendUi_header_signOut-item{padding:5px 0px 5px 30px;border-left:1px solid #b1b4b6;margin-left:auto}.frontendUi_header__signOut{display:flex}.frontendUi-header__content{margin-left:auto}.govuk-tag{font-family:"GDS Transport",arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:14px;font-size:.875rem;line-height:1;display:inline-block;padding-top:5px;padding-right:8px;padding-bottom:4px;padding-left:8px;outline:2px solid rgba(0,0,0,0);outline-offset:-2px;color:#fff !important;background-color:#1d70b8 !important;letter-spacing:1px !important;text-decoration:none !important;text-transform:uppercase !important}/*! Copyright (c) 2011 by Margaret Calvert & Henrik Kubel. All rights reserved. The font has been customised for exclusive use on gov.uk. This cut is not commercially available. */@font-face{font-family:"GDS Transport";font-style:normal;font-weight:normal;src:url("/assets/fonts/light-94a07e06a1-v2.woff2") format("woff2"),url("/assets/fonts/light-f591b13f7d-v2.woff") format("woff");font-display:fallback}@font-face{font-family:"GDS Transport";font-style:normal;font-weight:bold;src:url("/assets/fonts/bold-b542beb274-v2.woff2") format("woff2"),url("/assets/fonts/bold-affa96571d-v2.woff") format("woff");font-display:fallback}@media print{.govuk-tag{font-family:sans-serif}}@media(min-width: 40.0625em){.govuk-tag{font-size:16px;font-size:1rem;line-height:1}}@media print{.govuk-tag{font-size:14pt;line-height:1}}.language-select{margin:15px 0 15px 0}.language-select__list{margin-top:1em;text-align:right}.language-select__list-item{display:inline-block}.language-select__list-item:first-child::after{content:"";display:inline-block;position:relative;top:.1875em;height:1em;border-right:.09375em solid #000}.language-select__list-item a,.language-select__list-item [aria-current]{padding:.3125em}@media screen and (max-width: 641px){.language-select__list{float:none;text-align:left;padding-bottom:10px;border-bottom:1px solid #b1b4b6}}
|
|
1
|
+
@media(max-width: 640px){.govuk-header__navigation-item{border-left:none !important}.govuk-template--rebranded .govuk-header__navigation-list{padding-bottom:0px !important}.govuk-header__navigation-item{padding-top:5px !important}}.frontendUi_header_signOut-item{padding:5px 0px 5px 30px;border-left:1px solid #b1b4b6;margin-left:auto}.frontendUi_header_signOut-item--rebrand{border-left:none;padding:5px 0px 5px 30px;margin-left:auto;font-weight:700 !important}.frontendUi_header__signOut{display:flex;flex-wrap:wrap}.frontendUi-header__content{margin-left:auto}.govuk-header__navigation--signOut{padding:15px 0 15px !important}.govuk-template--rebranded .govuk-header__navigation{padding:15px 0 15px !important}@media(max-width: 640px){.govuk-header__navigation--signOut{padding:18px 0 8px !important}.govuk-template--rebranded .govuk-header__navigation{padding:18px 0 8px !important}}.govuk-template--rebranded .govuk-header__navigation-item a{font-weight:700 !important}.govuk-template--rebranded .govuk-header__navigation-item{padding-top:5px !important}@media(min-width: 20em)and (max-width: 48.0525em){.govuk-template--rebranded .govuk-header__navigation-list{padding-bottom:0px}}@media(max-width: 340px){.frontendUi-header__content{margin-left:unset}}.govuk-tag{font-family:"GDS Transport",arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:14px;font-size:.875rem;line-height:1;display:inline-block;padding-top:5px;padding-right:8px;padding-bottom:4px;padding-left:8px;outline:2px solid rgba(0,0,0,0);outline-offset:-2px;color:#fff !important;background-color:#1d70b8 !important;letter-spacing:1px !important;text-decoration:none !important;text-transform:uppercase !important}/*! Copyright (c) 2011 by Margaret Calvert & Henrik Kubel. All rights reserved. The font has been customised for exclusive use on gov.uk. This cut is not commercially available. */@font-face{font-family:"GDS Transport";font-style:normal;font-weight:normal;src:url("/assets/fonts/light-94a07e06a1-v2.woff2") format("woff2"),url("/assets/fonts/light-f591b13f7d-v2.woff") format("woff");font-display:fallback}@font-face{font-family:"GDS Transport";font-style:normal;font-weight:bold;src:url("/assets/fonts/bold-b542beb274-v2.woff2") format("woff2"),url("/assets/fonts/bold-affa96571d-v2.woff") format("woff");font-display:fallback}@media print{.govuk-tag{font-family:sans-serif}}@media(min-width: 40.0625em){.govuk-tag{font-size:16px;font-size:1rem;line-height:1}}@media print{.govuk-tag{font-size:14pt;line-height:1}}.language-select{margin:15px 0 15px 0}.language-select__list{margin-top:1em;text-align:right}.language-select__list-item{display:inline-block}.language-select__list-item:first-child::after{content:"";display:inline-block;position:relative;top:.1875em;height:1em;border-right:.09375em solid #000}.language-select__list-item a,.language-select__list-item [aria-current]{padding:.3125em}@media screen and (max-width: 641px){.language-select__list{float:none;text-align:left;padding-bottom:10px;border-bottom:1px solid #b1b4b6}}.spinner{width:80px;height:80px;border-radius:50%;border-width:12px;border-style:solid;border-color:#dee0e2;border-top-color:#005ea5;margin-bottom:govuk-spacing(3)}@media(forced-colors: active){.spinner{forced-color-adjust:none;border-top-color:rgba(0,0,0,0) !important}}@media not (prefers-reduced-motion){.spinner{-webkit-animation:spin 2s linear infinite;animation:spin 2s linear infinite}}@media(prefers-reduced-motion){.spinner{transform:rotate(0.125turn)}}.spinner__ready{border-color:#005ea5;-webkit-animation:none;animation:none}#spinner-container__error .spinner,#spinner-container__error .spinner-state-text{display:none}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(360deg)}}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}.centre{margin-left:auto;margin-right:auto;text-align:center;display:block}.govuk-footer__copyright-logo::before{background-image:url("../frontendUiAssets/images/govuk-crest.svg"),url("/frontendUiAssets/images/govuk-crest.svg") !important}.govuk-footer__copyright-logo{background-image:url("../frontendUiAssets/images/govuk-crest.svg"),url("/frontendUiAssets/images/govuk-crest.svg") !important}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const WaitInteractions = (() => {
|
|
4
|
+
const content = {
|
|
5
|
+
initial: {
|
|
6
|
+
spinnerState: "pending",
|
|
7
|
+
},
|
|
8
|
+
complete: { spinnerState: "completed" },
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const state = {
|
|
12
|
+
spinnerState: content.initial.spinnerState,
|
|
13
|
+
done: false,
|
|
14
|
+
virtualDom: [],
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const timers = {};
|
|
18
|
+
|
|
19
|
+
const createVirtualDom = () => {
|
|
20
|
+
const initialState = [
|
|
21
|
+
{
|
|
22
|
+
nodeName: "div",
|
|
23
|
+
id: "spinner",
|
|
24
|
+
classes: ["spinner", "spinner__pending", "centre", state.spinnerState],
|
|
25
|
+
},
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
return initialState;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const vDomHasChanged = (currentVDom, nextVDom) => {
|
|
32
|
+
return JSON.stringify(currentVDom) !== JSON.stringify(nextVDom);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const updateDom = () => {
|
|
36
|
+
const vDomChanged = vDomHasChanged(state.virtualDom, createVirtualDom());
|
|
37
|
+
const container = document.getElementById("spinner-container");
|
|
38
|
+
|
|
39
|
+
if (vDomChanged) {
|
|
40
|
+
state.virtualDom = createVirtualDom();
|
|
41
|
+
const elements = state?.virtualDom?.map(convert);
|
|
42
|
+
container?.replaceChildren(...elements);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (state.error) {
|
|
46
|
+
container?.classList.add("spinner-container__error");
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (state.done) {
|
|
50
|
+
clearInterval(timers.updateDomTimer);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const reflectCompletion = () => {
|
|
55
|
+
state.spinnerState = "spinner__ready";
|
|
56
|
+
state.spinnerStateText = content.complete.spinnerState;
|
|
57
|
+
state.done = true;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const reflectError = () => {
|
|
61
|
+
state.spinnerState = "spinner__failed";
|
|
62
|
+
state.done = true;
|
|
63
|
+
state.error = true;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const convert = (node) => {
|
|
67
|
+
const el = document.createElement(node.nodeName);
|
|
68
|
+
if (node.text) el.textContent = node.text;
|
|
69
|
+
if (node.innerHTML) el.innerHTML = node.innerHTML;
|
|
70
|
+
if (node.id) el.id = node.id;
|
|
71
|
+
if (node.classes) el.classList.add(...node.classes);
|
|
72
|
+
return el;
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const notInErrorOrDoneState = () => {
|
|
76
|
+
return !(state.done || state.error);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const requestIDProcessingStatus = async () => {
|
|
80
|
+
const apiRoute =
|
|
81
|
+
document?.getElementById("spinner-container")?.dataset.apiRoute;
|
|
82
|
+
try {
|
|
83
|
+
const response = await fetch(apiRoute);
|
|
84
|
+
|
|
85
|
+
if (response.status !== 200) {
|
|
86
|
+
throw new Error(`Status code ${response.status} received`);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const data = await response.json();
|
|
90
|
+
|
|
91
|
+
if (data.status === "Clear to proceed") {
|
|
92
|
+
reflectCompletion();
|
|
93
|
+
} else if (notInErrorOrDoneState()) {
|
|
94
|
+
setTimeout(async () => {
|
|
95
|
+
await requestIDProcessingStatus();
|
|
96
|
+
}, 1000);
|
|
97
|
+
}
|
|
98
|
+
} catch (e) {
|
|
99
|
+
console.log(e);
|
|
100
|
+
reflectError();
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
return {
|
|
105
|
+
state: state,
|
|
106
|
+
init: () => {
|
|
107
|
+
timers.updateDomTimer = setInterval(updateDom, 2000);
|
|
108
|
+
|
|
109
|
+
timers.abortUnresponsiveRequest = setTimeout(() => {
|
|
110
|
+
reflectError();
|
|
111
|
+
}, 15000);
|
|
112
|
+
|
|
113
|
+
updateDom();
|
|
114
|
+
|
|
115
|
+
requestIDProcessingStatus().then(() => {
|
|
116
|
+
updateDom();
|
|
117
|
+
});
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
})();
|
|
121
|
+
|
|
122
|
+
exports.WaitInteractions = WaitInteractions;
|
package/build/cjs/index.cjs
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var path = require('path');
|
|
4
|
+
var fs = require('fs');
|
|
5
|
+
|
|
3
6
|
var cookieBanner$1 = {
|
|
4
7
|
body1: "Rydym yn defnyddio rhai cwcis hanfodol i wneud i'r gwasanaeth hwn weithio.",
|
|
5
8
|
body2: "Hoffem osod cwcis ychwanegol er mwyn i ni allu cofio eich gosodiadau, deall sut mae pobl yn defnyddio'r gwasanaeth a gwneud gwelliannau.",
|
|
@@ -56,7 +59,8 @@ var footer$1 = {
|
|
|
56
59
|
};
|
|
57
60
|
var header$1 = {
|
|
58
61
|
signOut: "Allgofnodi",
|
|
59
|
-
ariaLabel: "GOV.UK One Login dewislen"
|
|
62
|
+
ariaLabel: "GOV.UK One Login dewislen",
|
|
63
|
+
signOutAriaLabel: "Allgofnodi"
|
|
60
64
|
};
|
|
61
65
|
var languageSelect$1 = {
|
|
62
66
|
ariaLabel: "Switcher iaith"
|
|
@@ -134,7 +138,8 @@ var footer = {
|
|
|
134
138
|
};
|
|
135
139
|
var header = {
|
|
136
140
|
signOut: "Sign Out",
|
|
137
|
-
ariaLabel: "GOV.UK One Login menu"
|
|
141
|
+
ariaLabel: "GOV.UK One Login menu",
|
|
142
|
+
signOutAriaLabel: "Sign out"
|
|
138
143
|
};
|
|
139
144
|
var languageSelect = {
|
|
140
145
|
ariaLabel: "Select language"
|
|
@@ -156,20 +161,24 @@ var translationEn = {
|
|
|
156
161
|
skipLink: skipLink
|
|
157
162
|
};
|
|
158
163
|
|
|
164
|
+
// Implementation
|
|
165
|
+
function frontendUiMiddleware(req, res, next) {
|
|
166
|
+
res.locals.translations = req.i18n.store.data[req.i18n.language];
|
|
167
|
+
res.locals.basePath = process.cwd();
|
|
168
|
+
next();
|
|
169
|
+
}
|
|
159
170
|
const setFrontendUiTranslations = (instanceI18n) => {
|
|
160
171
|
instanceI18n.addResourceBundle("en", "translation", translationEn, true, false);
|
|
161
172
|
instanceI18n.addResourceBundle("cy", "translation", translationCy, true, false);
|
|
162
173
|
};
|
|
163
|
-
const frontendUiMiddleware = (req, res, next) => {
|
|
164
|
-
res.locals.translations = req.i18n.store.data[req.i18n.language];
|
|
165
|
-
next();
|
|
166
|
-
};
|
|
167
174
|
const frontendUiMiddlewareIdentityBypass = (req, res, next) => {
|
|
168
175
|
const localTranslations = {
|
|
169
176
|
en: translationEn,
|
|
170
|
-
cy: translationCy
|
|
177
|
+
cy: translationCy,
|
|
171
178
|
};
|
|
172
|
-
|
|
179
|
+
const language = req.i18n.language;
|
|
180
|
+
res.locals.translations = localTranslations[language] || {};
|
|
181
|
+
res.locals.basePath = process.cwd();
|
|
173
182
|
next();
|
|
174
183
|
};
|
|
175
184
|
function addLanguageParam(language, url) {
|
|
@@ -187,9 +196,36 @@ function contactUsUrl(baseUrl, urlToAppend) {
|
|
|
187
196
|
const searchParams = new URLSearchParams({ fromURL: urlToAppend });
|
|
188
197
|
return `${baseUrl}?${searchParams.toString()}`;
|
|
189
198
|
}
|
|
199
|
+
const setBaseTranslations = (instanceI18n, filePath) => {
|
|
200
|
+
["cy", "en"].forEach((locale) => {
|
|
201
|
+
instanceI18n.addResourceBundle(locale, "translation", getTranslationObject(locale, filePath));
|
|
202
|
+
});
|
|
203
|
+
};
|
|
204
|
+
const getTranslationObject = (locale, filepath) => {
|
|
205
|
+
const possiblePaths = [
|
|
206
|
+
path.resolve("locales", locale, "translation.json"),
|
|
207
|
+
path.resolve("src/locales", locale, "translation.json"),
|
|
208
|
+
path.resolve(filepath !== null && filepath !== void 0 ? filepath : "", locale, "translation.json"),
|
|
209
|
+
];
|
|
210
|
+
for (const filePath of possiblePaths) {
|
|
211
|
+
if (fs.existsSync(filePath)) {
|
|
212
|
+
try {
|
|
213
|
+
const fileContent = fs.readFileSync(filePath, "utf8");
|
|
214
|
+
return JSON.parse(fileContent);
|
|
215
|
+
}
|
|
216
|
+
catch (error) {
|
|
217
|
+
console.error(`Error reading or parsing translation file at ${filePath}:`, error);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
console.warn(`No translation file found for locale: ${locale}`);
|
|
222
|
+
return {}; // Return an empty object as a fallback
|
|
223
|
+
};
|
|
190
224
|
|
|
191
225
|
exports.addLanguageParam = addLanguageParam;
|
|
192
226
|
exports.contactUsUrl = contactUsUrl;
|
|
193
227
|
exports.frontendUiMiddleware = frontendUiMiddleware;
|
|
194
228
|
exports.frontendUiMiddlewareIdentityBypass = frontendUiMiddlewareIdentityBypass;
|
|
229
|
+
exports.getTranslationObject = getTranslationObject;
|
|
230
|
+
exports.setBaseTranslations = setBaseTranslations;
|
|
195
231
|
exports.setFrontendUiTranslations = setFrontendUiTranslations;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import i18next from "i18next";
|
|
2
|
+
import { NextFunction, Request, Response } from "express";
|
|
3
|
+
interface I18nData {
|
|
4
|
+
language: string;
|
|
5
|
+
store: {
|
|
6
|
+
data: {
|
|
7
|
+
[key: string]: unknown;
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
interface ExpressRequest extends Request {
|
|
12
|
+
i18n: I18nData;
|
|
13
|
+
}
|
|
14
|
+
interface ExpressResponse extends Response {
|
|
15
|
+
locals: {
|
|
16
|
+
translations: unknown;
|
|
17
|
+
basePath?: string;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
interface PlainRequest {
|
|
21
|
+
i18n: I18nData;
|
|
22
|
+
}
|
|
23
|
+
interface PlainResponse {
|
|
24
|
+
locals: {
|
|
25
|
+
translations: unknown;
|
|
26
|
+
basePath?: string;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export declare function frontendUiMiddleware(req: ExpressRequest, res: ExpressResponse, next: NextFunction): void;
|
|
30
|
+
export declare function frontendUiMiddleware(req: PlainRequest, res: PlainResponse, next: NextFunction): void;
|
|
31
|
+
export declare const setFrontendUiTranslations: (instanceI18n: typeof i18next) => void;
|
|
32
|
+
export declare const frontendUiMiddlewareIdentityBypass: (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => void;
|
|
33
|
+
export declare function addLanguageParam(language: string, url?: URL): string;
|
|
34
|
+
export declare function contactUsUrl(baseUrl: string, urlToAppend: string): string | null;
|
|
35
|
+
export declare const setBaseTranslations: (instanceI18n: typeof i18next, filePath?: string) => void;
|
|
36
|
+
export declare const getTranslationObject: (locale: string, filepath?: string) => Record<string, unknown>;
|
|
37
|
+
export {};
|
|
38
|
+
//# sourceMappingURL=index.d.ts.map
|
package/build/cjs/index.d.ts
CHANGED
|
@@ -1,29 +1,38 @@
|
|
|
1
1
|
import i18next from "i18next";
|
|
2
2
|
import { NextFunction, Request, Response } from "express";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
data: {
|
|
9
|
-
[key: string]: unknown;
|
|
10
|
-
};
|
|
3
|
+
interface I18nData {
|
|
4
|
+
language: string;
|
|
5
|
+
store: {
|
|
6
|
+
data: {
|
|
7
|
+
[key: string]: unknown;
|
|
11
8
|
};
|
|
12
9
|
};
|
|
13
|
-
}
|
|
10
|
+
}
|
|
11
|
+
interface ExpressRequest extends Request {
|
|
12
|
+
i18n: I18nData;
|
|
13
|
+
}
|
|
14
|
+
interface ExpressResponse extends Response {
|
|
14
15
|
locals: {
|
|
15
16
|
translations: unknown;
|
|
17
|
+
basePath?: string;
|
|
16
18
|
};
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
i18n:
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}, res: Response & {
|
|
19
|
+
}
|
|
20
|
+
interface PlainRequest {
|
|
21
|
+
i18n: I18nData;
|
|
22
|
+
}
|
|
23
|
+
interface PlainResponse {
|
|
23
24
|
locals: {
|
|
24
25
|
translations: unknown;
|
|
26
|
+
basePath?: string;
|
|
25
27
|
};
|
|
26
|
-
}
|
|
28
|
+
}
|
|
29
|
+
export declare function frontendUiMiddleware(req: ExpressRequest, res: ExpressResponse, next: NextFunction): void;
|
|
30
|
+
export declare function frontendUiMiddleware(req: PlainRequest, res: PlainResponse, next: NextFunction): void;
|
|
31
|
+
export declare const setFrontendUiTranslations: (instanceI18n: typeof i18next) => void;
|
|
32
|
+
export declare const frontendUiMiddlewareIdentityBypass: (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => void;
|
|
27
33
|
export declare function addLanguageParam(language: string, url?: URL): string;
|
|
28
34
|
export declare function contactUsUrl(baseUrl: string, urlToAppend: string): string | null;
|
|
35
|
+
export declare const setBaseTranslations: (instanceI18n: typeof i18next, filePath?: string) => void;
|
|
36
|
+
export declare const getTranslationObject: (locale: string, filepath?: string) => Record<string, unknown>;
|
|
37
|
+
export {};
|
|
29
38
|
//# sourceMappingURL=index.d.ts.map
|
package/build/cjs/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAQ1D,UAAU,QAAQ;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE;QACL,IAAI,EAAE;YAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;SAAE,CAAC;KAClC,CAAC;CACH;AAED,UAAU,cAAe,SAAQ,OAAO;IACtC,IAAI,EAAE,QAAQ,CAAC;CAChB;AAED,UAAU,eAAgB,SAAQ,QAAQ;IACxC,MAAM,EAAE;QACN,YAAY,EAAE,OAAO,CAAC;QACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED,UAAU,YAAY;IACpB,IAAI,EAAE,QAAQ,CAAC;CAChB;AAED,UAAU,aAAa;IACrB,MAAM,EAAE;QACN,YAAY,EAAE,OAAO,CAAC;QACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAGD,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,cAAc,EACnB,GAAG,EAAE,eAAe,EACpB,IAAI,EAAE,YAAY,GACjB,IAAI,CAAC;AAER,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,YAAY,EACjB,GAAG,EAAE,aAAa,EAClB,IAAI,EAAE,YAAY,GACjB,IAAI,CAAC;AAaR,eAAO,MAAM,yBAAyB,GAAI,cAAc,OAAO,OAAO,SAerE,CAAC;AAGF,eAAO,MAAM,kCAAkC,GAC7C,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,MAAM,YAAY,SAUnB,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,UAU3D;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,iBAMhE;AAED,eAAO,MAAM,mBAAmB,GAC9B,cAAc,OAAO,OAAO,EAC5B,WAAW,MAAM,SASlB,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAC/B,QAAQ,MAAM,EACd,WAAW,MAAM,KAChB,MAAM,CAAC,MAAM,EAAE,OAAO,CAuBxB,CAAC"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
{% extends "govuk/template.njk" %}
|
|
2
|
+
|
|
3
|
+
{% from "frontend-ui/build/components/cookie-banner/macro.njk" import frontendUiCookieBanner %}
|
|
4
|
+
{% from "frontend-ui/build/components/phase-banner/macro.njk" import frontendUiPhaseBanner %}
|
|
5
|
+
{% from "frontend-ui/build/components/header/macro.njk" import frontendUiHeader %}
|
|
6
|
+
{% from "frontend-ui/build/components/footer/macro.njk" import frontendUiFooter %}
|
|
7
|
+
{% from "govuk/components/back-link/macro.njk" import govukBackLink %}
|
|
8
|
+
{% from "frontend-ui/build/components/language-select/macro.njk" import frontendUiLanguageSelect %}
|
|
9
|
+
|
|
10
|
+
{% if May_2025_Rebrand %}
|
|
11
|
+
{%set htmlClasses = 'govuk-template--rebranded'%}
|
|
12
|
+
{% endif %}
|
|
13
|
+
|
|
14
|
+
{% if strategicAppChannel == true %}
|
|
15
|
+
{% set htmlClasses = 'govuk-template__mobile' %}
|
|
16
|
+
{% endif %}
|
|
17
|
+
|
|
18
|
+
{% block head %}
|
|
19
|
+
<!--[if !IE 8]><!-->
|
|
20
|
+
<link href="/public/style.css" rel="stylesheet">
|
|
21
|
+
<link rel="stylesheet" href="/public/frontendUi.css"/>
|
|
22
|
+
<!--<![endif]-->
|
|
23
|
+
|
|
24
|
+
<!--[if IE 8]>
|
|
25
|
+
<link href="/govuk-frontend/all-ie8.css" rel="stylesheet">
|
|
26
|
+
<![endif]-->
|
|
27
|
+
|
|
28
|
+
<!--[if lt IE 9]>
|
|
29
|
+
<script src="/html5-shiv/html5shiv.js"></script>
|
|
30
|
+
<![endif]-->
|
|
31
|
+
|
|
32
|
+
{% block headMetaData %}{% endblock %}
|
|
33
|
+
{% endblock %}
|
|
34
|
+
|
|
35
|
+
{% block pageTitle %}
|
|
36
|
+
{% if error or errors %}
|
|
37
|
+
{{ 'general.errorTitlePrefix' | translate }} -
|
|
38
|
+
{% endif %}
|
|
39
|
+
{% if pageTitleName %}
|
|
40
|
+
{{ pageTitleName }} -
|
|
41
|
+
{% endif %}
|
|
42
|
+
{{ 'general.serviceNameTitle' | translate }}
|
|
43
|
+
{% endblock %}
|
|
44
|
+
|
|
45
|
+
{% block bodyStart %}
|
|
46
|
+
{% block cookieBanner %}
|
|
47
|
+
{{ frontendUiCookieBanner({
|
|
48
|
+
translations: translations.translation.cookieBanner
|
|
49
|
+
}) }}
|
|
50
|
+
{% endblock %}
|
|
51
|
+
{% endblock %}
|
|
52
|
+
|
|
53
|
+
{% set phaseBannerClasses = "test-banner" if showTestBanner %}
|
|
54
|
+
|
|
55
|
+
{% block header %}
|
|
56
|
+
{{ frontendUiHeader({
|
|
57
|
+
translations: translations.translation.header,
|
|
58
|
+
homepageUrl: "https://www.gov.uk",
|
|
59
|
+
classes: phaseBannerClasses
|
|
60
|
+
}) }}
|
|
61
|
+
{% endblock %}
|
|
62
|
+
|
|
63
|
+
{% if showTestBanner %}
|
|
64
|
+
{% set phaseBannerText = 'general.phaseBanner.testEnvironmentMessage' | translate %}
|
|
65
|
+
{% else %}
|
|
66
|
+
{% set phaseBannerText = 'phaseBanner.text' | translate %}
|
|
67
|
+
{% endif %}
|
|
68
|
+
|
|
69
|
+
{% if showTestBanner %}
|
|
70
|
+
{% set phaseBannerTag = 'general.phaseBanner.tag.test' | translate %}
|
|
71
|
+
{% else %}
|
|
72
|
+
{% set phaseBannerTag = 'general.phaseBanner.tag.beta' | translate %}
|
|
73
|
+
{% endif %}
|
|
74
|
+
|
|
75
|
+
{% block main %}
|
|
76
|
+
<div class="govuk-width-container {{ containerClasses }}">
|
|
77
|
+
{{ frontendUiPhaseBanner({
|
|
78
|
+
translations: translations.translation.phaseBanner,
|
|
79
|
+
url: currentUrl,
|
|
80
|
+
contactUrl: contactUsLinkUrl,
|
|
81
|
+
tag: phaseBannerTag,
|
|
82
|
+
phaseBannerText: phaseBannerText
|
|
83
|
+
}) }}
|
|
84
|
+
{% block beforeContent %}{% endblock %}
|
|
85
|
+
{% if languageToggleEnabled %}
|
|
86
|
+
{{ frontendUiLanguageSelect({
|
|
87
|
+
translations: translations.translation.languageSelect,
|
|
88
|
+
url: currentUrl,
|
|
89
|
+
activeLanguage: htmlLang
|
|
90
|
+
}) }}
|
|
91
|
+
{% endif %}
|
|
92
|
+
{% if showBack %}
|
|
93
|
+
{{ govukBackLink({
|
|
94
|
+
text: "general.back" | translate,
|
|
95
|
+
href: hrefBack
|
|
96
|
+
}) }}
|
|
97
|
+
{% endif %}
|
|
98
|
+
<main class="govuk-main-wrapper {{ mainClasses }}" id="main-content" role="main" {% if mainLang %} lang="{{ mainLang }}"{% endif %}>
|
|
99
|
+
<div class="govuk-grid-row">
|
|
100
|
+
<div class="govuk-grid-column-two-thirds {{ rowClasses }}">
|
|
101
|
+
{% block content %}{% endblock %}
|
|
102
|
+
</div>
|
|
103
|
+
</div>
|
|
104
|
+
</main>
|
|
105
|
+
</div>
|
|
106
|
+
{% endblock %}
|
|
107
|
+
|
|
108
|
+
{% block footer %}
|
|
109
|
+
{% if strategicAppChannel === true %}
|
|
110
|
+
{% else %}
|
|
111
|
+
{{ frontendUiFooter({
|
|
112
|
+
translations: translations.translation.footer
|
|
113
|
+
}) }}
|
|
114
|
+
{% endif %}
|
|
115
|
+
{% endblock %}
|
|
116
|
+
|
|
117
|
+
{% block bodyEnd %}
|
|
118
|
+
{% block scripts %}{% endblock %}
|
|
119
|
+
<script type="text/javascript" src="/public/scripts/dataLayerEvents.js"></script>
|
|
120
|
+
<script type="text/javascript" src="/public/scripts/application.js"></script>
|
|
121
|
+
<script type="text/javascript" src="/public/scripts/all.js"></script>
|
|
122
|
+
<script type="text/javascript" src="/public/scripts/analytics.js"></script>
|
|
123
|
+
<script type="text/javascript" {% if scriptNonce %} nonce="{{ scriptNonce }}"{% endif %}>
|
|
124
|
+
if (window.DI) {
|
|
125
|
+
if (window.DI.appInit) {
|
|
126
|
+
window.DI.appInit({
|
|
127
|
+
ga4ContainerId: "{{ga4ContainerId}}",
|
|
128
|
+
uaContainerId: "not used" // We don't use UA anymore, but it's a required param
|
|
129
|
+
}, {
|
|
130
|
+
isDataSensitive: false,
|
|
131
|
+
enableGa4Tracking: {{isGa4Enabled}},
|
|
132
|
+
cookieDomain: "{{analyticsCookieDomain}}"
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
</script>
|
|
137
|
+
{% endblock %}
|