Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
c80888e
chore: ignore .worktrees directory
alexluckett Apr 17, 2026
4318ab1
feat: add runner en-GB translation file
alexluckett Apr 17, 2026
a4f7aaa
feat: add runner i18n module with t() and resolveLanguage()
alexluckett Apr 17, 2026
b49f0d5
feat: implement i18n module using i18next createInstance()
alexluckett Apr 17, 2026
b75b6b0
fix: correct t() return type and tidy resolveLanguage comment spacing
alexluckett Apr 17, 2026
16b6c06
feat: add t() translation helper to nunjucks global context
alexluckett Apr 17, 2026
040fb6c
feat: resolve form language in help route handlers
alexluckett Apr 17, 2026
8b27a80
feat: resolve form language in save-and-exit route handlers
alexluckett Apr 17, 2026
95f9b64
feat: translate save-and-exit views
alexluckett Apr 17, 2026
a4f56d2
feat: translate help views
alexluckett Apr 17, 2026
4aed7cd
feat: translate error and confirmation views
alexluckett Apr 17, 2026
a183c20
fix: correct mismatched closing tag in save-and-exit confirmation view
alexluckett Apr 17, 2026
5f60681
feat: translate confirmation view fallback strings
alexluckett Apr 17, 2026
094b1a5
chore: add t() translation helper to ViewContext typedef
alexluckett Apr 17, 2026
23124af
chore: fix import formatting in i18n test
alexluckett Apr 17, 2026
2bdf849
feat: resolve form language in remaining help route handlers
alexluckett Apr 17, 2026
91a2f06
feat: add x-pirate translation for runner views
alexluckett Apr 17, 2026
855e629
feat: merge i18n feature branch
alexluckett Apr 17, 2026
c71879e
more translations
alexluckett May 11, 2026
bd7c1e1
Stash
jbarnsley10 Jun 24, 2026
4485983
Merge branch 'main' into feature/i18n-welsh
jbarnsley10 Jun 24, 2026
06ac20a
Lint
jbarnsley10 Jun 24, 2026
d5018a2
Stash
jbarnsley10 Jun 24, 2026
bc055eb
Type fixes
jbarnsley10 Jun 25, 2026
c1362f5
Stash for now
jbarnsley10 Jun 29, 2026
ff21c35
Fixed most of the tests
jbarnsley10 Jun 29, 2026
99af948
Merge branch 'main' into feature/i18n-welsh
davidjamesstone Jun 29, 2026
8a01c06
Changes to resolveLanguage
davidjamesstone Jun 30, 2026
5f33636
Update resolveLanguage
davidjamesstone Jun 30, 2026
a1157c6
Added language options in header
jbarnsley10 Jun 30, 2026
90eb4df
Populated all Welsh translations
jbarnsley10 Jul 1, 2026
cf078db
Some corrections to Welsh translations
jbarnsley10 Jul 1, 2026
5c3b6f7
Update to conform to GetLanguageHandler interface
davidjamesstone Jul 1, 2026
570529b
Fix confirmation-email test
davidjamesstone Jul 2, 2026
095d854
Added getFormTranslator capabilty with caching so runner can translat…
davidjamesstone Jul 3, 2026
dd0d382
Fix confirmation-email test
davidjamesstone Jul 3, 2026
6ff54d6
Fixed save-and-exit test
davidjamesstone Jul 3, 2026
0915738
Fix models/save-and-exit test
davidjamesstone Jul 3, 2026
ea0ce9d
Fix import typo
davidjamesstone Jul 6, 2026
1306e8c
Handles form name and confirmation page
jbarnsley10 Jul 8, 2026
e15264f
Merge branch 'main' into feature/i18n-welsh
jbarnsley10 Jul 8, 2026
e747749
Corrected submission guidance
jbarnsley10 Jul 8, 2026
696119c
Fix tests where metadata missing in FormModel
davidjamesstone Jul 8, 2026
9e054d3
Temp stash - one failing test
jbarnsley10 Jul 9, 2026
a41fab7
Implement metadata translator
jbarnsley10 Jul 10, 2026
da3833b
Split into two translators - one for plugin routes, the other for ext…
jbarnsley10 Jul 13, 2026
779a3e2
Added docs
jbarnsley10 Jul 13, 2026
cb11059
Added language selector to all routes
jbarnsley10 Jul 14, 2026
4a28b0a
Fixed collision of translator instances
jbarnsley10 Jul 14, 2026
09b5c34
Fixed issue with selecting language when 'force' existed in URL
jbarnsley10 Jul 16, 2026
4aad408
Bumped plugin to use Welsh translation
jbarnsley10 Jul 16, 2026
34f1a74
Sonar fixes
jbarnsley10 Jul 17, 2026
1c0a1ee
Removed TODO
jbarnsley10 Jul 17, 2026
7e6ef7d
Fixed submissionGuidance
jbarnsley10 Jul 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ UPLOADER_BUCKET_NAME=
UPLOADER_URL=http://uploader.127.0.0.1.sslip.io:7300

GOOGLE_ANALYTICS_TRACKING_ID=
GOOGLE_ANALYTICS_CONTAINER_ID=
GOOGLE_TAG_MANAGER_CONTAINER_ID=

USE_SINGLE_INSTANCE_CACHE=true

Expand All @@ -42,7 +42,6 @@ LOG_LEVEL=debug
LOG_FORMAT=pino-pretty
STAGING_PREFIX=staging
SERVICE_BANNER_TEXT=
GOOGLE_TAG_MANAGER_CONTAINER_ID=
SAVE_AND_EXIT_EXPIRY_IN_DAYS=28
STORE_COMPLETED_APPLICATIONS_FOR=9 months
STORE_FEEDBACK_FOR=9 months
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ coverage
.cache
.env
tsconfig.tsbuildinfo
.worktrees/
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ The designer is no longer a plugin and is responsible for running itself on defa
- [⚠️ See config for default values for each environment](#️-see-config-for-default-values-for-each-environment)
- [Testing](#testing)
- [Outputs](#outputs)
- [Multi-language support](#multi-language-support)
- [Licence](#licence)
- [About the licence](#about-the-licence)

Expand Down Expand Up @@ -233,6 +234,11 @@ Additional steps are required for the different output types.
- A GOV.UK [notify](https://www.notifications.service.gov.uk) is required
- For each notification you wish to send, a template must be set up. If there are 'personalisations' they must match the configuration

# Multi-language support

The runner can support multiple languages, specifically English and Welsh.
See [multi-language](./docs/multi-language.md) for more information.

## Licence

THIS INFORMATION IS LICENSED UNDER THE CONDITIONS OF THE OPEN GOVERNMENT LICENCE found at:
Expand Down
49 changes: 49 additions & 0 deletions docs/multi-language.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Multi-language (specifically English and Welsh)

The `engine-plugin` and `runner` support multi-languages (if configured).
Additional languages are configured by adding translations json files and adding a `translations` property under the `metadata` property of the form definition.
You can use the Designer to edit Welsh translations for your form (to insert the necessary values in the `metadata.translations` property).

Currently only English and Welsh are configured but other languages could be added if desired.

## Forms engine plugin

The `engine-plugin` handles translations at two levels:

1. Boilerplate text - a translation file per language exists in `plugin` (`en-GB.json` and `cy.json`). These provide English and Welsh for each boilerplate text element, such as the feedback link url and text, or the error summary etc.
2. Dynamic form text - English translations are read from the form definition (such as component title, short description etc), whereas Welsh translations are read from the `metadata.translations.cy` property of the form definition.

The translator provides a series of functions:

- t(key) - a general translation function that takes a key (for example 'validation.numberMax') and returns either the appropriate English text or Welsh text deending on which is the current language
- tPage(key) - returns the appropriate translations for page elements, such as title, guidance etc.
- tComponent(key) - returns the appropriate translations for components, such as question text, hint, short description etc.
- tSection(key) - returns the appropriate translations for sections
- tListItem(key) - returns the appropriate translations for list items since each list value (e.g from a radio/checkbox etc) must have a translated equivalent
- tForm(key) - returns the appropriate translations for form-level elements. Currently this only handles the form name.

## Forms runner

The `runner` handles translations at two levels and sits on top of the translations from `engine-plugin`:

1. Boilerplate text - a translation file per language exists in `runner` (`en-GB.json` and `cy.json`). These provide English and Welsh for each boilerplate text element that lives outside of the `engine-plugin`, such as the footer links and 'save and exit' pages.
2. Dynamic form overview text - English translations are read from the form metadata (such as 'what happens next' or contact information), whereas Welsh translations are read from the `metadata.translations.cy` property of the form definition (specifically entries starting with `form.`).

The translator provides a series of functions:

- t(key) - a general translation function that takes a key and returns either the appropriate English text or Welsh text deending on which is the current language
- tR(key) - returns the appropriate translations for elements specific to the `runner` (to avoid confusion with the `engine-plugin` translator functions)
- tForm(key) - returns the appropriate translations for the form-level metadata elements (such as 'what happens next' or contact information), and also the form name.

## Language selector

If additional languages are defined, a language selector is displayed in the top-right of the form.
Additional languages must be set within the Nunjucks/Vision global `context` in order for the language selector to display.
The language selector should be shown for all plugin routes as well as all external routes (such as save-and-exit and static pages) when additional languages have been defined for the form.

## Accessing the translator

The translator should be available from the Nunjucks/Vision global `context` (for `engine-plugin` routes) and from the `context` attribute within the model for external routes. Either way, the translator should be accessible in a Nunjucks/Vision page using the attribute `context.translator`. This is particularly important for rendering `layout.html` since it references `context.translator.tForm('title')`. This must be available for both plugin routes and external routes alike.

If you wanted to translate a runner-spcific piece of text, for example the footer links, you would call `context.translator.tR('my-translation-element-name')`.
If you wanted to translate form-spcific metadtaa values, for example contact information, you would call `context.translator.tForm('contact.oneline.url')` to get the translation of for the key `form.contact.online.url` under `metatdata.translations.cy` - not the extra `form.` in the key name inside the form definition.
1 change: 0 additions & 1 deletion jest.setup.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ process.env.SUBMISSION_URL = 'https://test-submission-api.cdp-int.defra.cloud'
process.env.UPLOADER_URL = 'https://test-uploader.cdp-int.defra.cloud'
process.env.UPLOADER_BUCKET_NAME = 'dummy-bucket'
process.env.GOOGLE_TAG_MANAGER_CONTAINER_ID = 'GTM-XXXXXXXX'
process.env.GOOGLE_ANALYTICS_TRACKING_ID = '12345'
process.env.GOOGLE_ANALYTICS_CONTAINER_ID = 'YYYYYYYYYY'
process.env.USE_SINGLE_INSTANCE_CACHE = 'true'
process.env.BASE_URL = 'http://localhost:3009'
Expand Down
Loading
Loading