Skip to content

Add Mobility gem and configure text fields to be translatable#2272

Merged
DavidBiddle merged 15 commits into
mainfrom
add-mobility
Oct 20, 2025
Merged

Add Mobility gem and configure text fields to be translatable#2272
DavidBiddle merged 15 commits into
mainfrom
add-mobility

Conversation

@DavidBiddle
Copy link
Copy Markdown
Contributor

@DavidBiddle DavidBiddle commented Oct 8, 2025

What problem does this pull request solve?

Trello card: https://trello.com/c/WvPnJSu4/2612-backend-parts-of-option-2-for-welsh-feature-add-mobility-gem-and-add-tables-for-welsh-content

Add Mobility Gem

This PR adds the mobility gem for storing Welsh translations. It configures the
gem to use the table backend and contains migrations to add translations to Form, Page and Condition.

See ADR 46 for more context on the table backend, ADR 43 for more on the gem and other backend strategies and ADR 44 for a high-level overview for how welsh forms will be to form fillers.

This PR doesn't include any UI to edit translations, or any logic to update form documents in other languages.

Merging this PR should not affect any existing forms or any features.

A high-level overview of the Mobility gem

Mobility is a gem which allows you to store translations for your models. It's configurable to use different storage methods (known as backends) and behaviours for accessing translations.

We're using the table backend, which stores translations in a separate table alongside the main model table.

For example, the translations for a Form model would be stored in a table called form_translations.

This table contains columns for each attribute being translated, and a locale column to store the locale of the translation.

Mobility adds associations, attribute accessors and other helpers to your models.

You can test this PR by starting the rails console and accessing attributes on a form.

To get the name of a form:

form = Form.first
form.name

To get the Welsh name of a form:

form.name(locale: :cy)

You can also use the _cy suffix to get and set the Welsh name of a form:

form.name_cy = "Welsh name"

To create a form document using the welsh translations:

Mobility.with_locale(:cy) do
  form.as_form_document
end

Translated attributes

The following attributes are translated:

Forms

name
privacy_policy_url
support_email
support_phone
support_url
support_url_text
declaration_text
what_happens_next_markdown
payment_url

Pages

question_text
hint_text
answer_settings
page_heading
guidance_markdown

Conditions

answer_value
exit_page_markdown
exit_page_heading

We are adding translations for answer_type and answer_settings.

Answer_type is a string which represents the type of answer, for example "selection" or "text" or "number".

Including a translation means that we can have a different answer type for Welsh and English, although that may cause issues when filling in a form.

Answer_settings is a hash which contains the settings for the answer type.

For example, for a selection answer type, the answer settings will contain a list of options.

Have a translation for answer_settings means that we can have different options for selections in Welsh and English.

Things to consider when reviewing

  • Ensure that you consider the wider context.
  • Does it work when run on your machine?
  • Is it clear what the code is doing?
  • Do the commit messages explain why the changes were made?
  • Are there all the unit tests needed?
  • Do the end to end tests need updating before these changes will pass?
  • Has all relevant documentation been updated?

Comment thread app/models/page.rb Outdated
Comment thread config/application.rb Outdated
@thomasiles thomasiles changed the title WIP Add Mobility gem and configure text fields to be translatable Add Mobility gem and configure text fields to be translatable Oct 15, 2025
@thomasiles thomasiles marked this pull request as ready for review October 15, 2025 08:08
Comment thread app/models/form.rb Outdated
Copy link
Copy Markdown
Contributor

@thomasiles thomasiles left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good to me

DavidBiddle and others added 15 commits October 20, 2025 14:34
Configures the Mobility gem to fall back to English and to generate
locale accessor methods (e.g. `question_text_en`) for translated fields.
We use Condition#exit_page_markdown to check if the condition is an exit
page.

In our tests setup we set exit_page_markdown to "" and check the result
of #exit_page?.

Before adding the mobility gem, this test passed.

Adding mobility translations causes the test to fail because "" is
normalised to nil.

The translation is set to presence: false so that empty strings are
preserved.

We might need to be careful about similar issues in the future. We may
also want to explicitly check the English version of the translation to
ensure the English and welsh versions are consistent.
This commit adds tests for the translations of the form model.

We might not want to do this for every attribute, but I found an issue
when manually setting the name of a form.
In the Page model, the jsonb answer_settings column is used to store
settings for the page, such as the selection options for a selection
page.

The page model uses the DataStructType when loading and saving the
answers from the database.

Answer_settings is part of the translations for the page, so we need
to make the same change to the answer_settings attribute for the
translations.

Extending from the Mobility dynamically creates a new model class for
the translations.

https://www.rubydoc.info/gems/mobility/Mobility/Backends/Table

We open the translation model class and add the answer_settings
attribute after this.
Add tests for Page translations.

We take to set specific values for answer_settings and answer_type in
the translations.

answer_type has validation with a limited set of values.

answer_settings is a json hash converted to a DataStruct object.
We set the form_slug of form when the name is set.

Form_name is translated, but form_slug stays in English regardless of
locale.

Previously we were setting [:form_slug] directly, which meant that
form_slug was being set to the Welsh text for both English and Welsh if
the Welsh name of the form changed.

This commit changes the way we set form_slug, to always use the English
name to generate the slug.
@sonarqubecloud
Copy link
Copy Markdown

@github-actions
Copy link
Copy Markdown

🎉 A review copy of this PR has been deployed! You can reach it at: https://pr-2272.admin.review.forms.service.gov.uk/

It may take 5 minutes or so for the application to be fully deployed and working. If it still isn't ready
after 5 minutes, there may be something wrong with the ECS task. You will need to go to the integration AWS account
to debug, or otherwise ask an infrastructure person.

For the sign in details and more information, see the review apps wiki page.

@DavidBiddle DavidBiddle merged commit 26f35fd into main Oct 20, 2025
6 checks passed
@DavidBiddle DavidBiddle deleted the add-mobility branch October 20, 2025 13:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants