Skip to content

fix: validateLanguage keeps the player's language instead of always en_GB (#937) - #1014

Open
ismisepaul wants to merge 3 commits into
devfrom
dev#937-validate-language
Open

ismisepaul wants to merge 3 commits into
devfrom
dev#937-validate-language

Conversation

@ismisepaul

@ismisepaul ismisepaul commented Oct 25, 2026 •

Copy link
Copy Markdown
Member

⚠️ Manual testing required before merging

The unit test proves the language code is now kept. Whether lessons then really answer in that language depends on each level's translation files, which only a running app shows.

Please run this branch, follow the steps, and comment on this PR with the result: pass, or the step that failed and what you saw.

Branch: dev#937-validate-language

Set up. Use a machine where the Shepherd Docker volumes can be thrown away: down -v deletes their data. JDK 17 and Maven 3.9.2+ are needed.

git fetch origin
git checkout 'dev#937-validate-language'
mvn -Pdocker clean install -DskipTests
docker compose down -v
docker compose up -d --build
  1. Open https://localhost, accept the self-signed certificate warning, log in as admin / password and set a new password when asked.
  2. On the Get Started page, tick Enable Unsafe Levels and click Open All Levels.
  3. Admin → Module Management → Change Module Layout → Open Floor, then reload the page, so every level is listed on the left.

Test

  1. Log out. On the login page, choose Español in the language picker, then log in.
  2. Open the SQL Injection lesson and submit test. The reply should be in Spanish.
  3. Repeat with Français, and once more with English to check it switches back.
  4. Spot-check two or three challenges (e.g. Insecure Cryptographic Storage Challenge 4): their replies should follow the chosen language wherever a translation exists.

It's broken if: replies stay in English after you pick Spanish or French, or a page shows an error after you switch language.


Fixes #937.

What

Validate.validateLanguage accepted a session lang only if it matched .[a-z]{2}-[A-Z]{2}$. Nothing stores that format: the picker (translation-select.jsp) stores two-letter codes (es, fr, …), and translation.jsp stores the request Locale (es_ES). So it always returned en_GB, and every lesson and challenge answered in English, whatever language the player picked.

It now accepts a two-letter language, optionally followed by a region (es, es_ES, pt-BR), and returns the language when it is one the picker offers: en, es, fr, pt, ga, zh, hi, ru. Anything else, including a missing session or attribute, still falls back to en_GB.

Tests

ValidateLanguageTest (unit):

  • the picker codes are kept;
  • es_ES, pt-BR and a Locale object are reduced to the language;
  • unsupported or malformed values fall back to en_GB: de, xen-GB, EN, english, ../es, es_ES_x and the empty string;
  • a missing session or attribute falls back to en_GB.

It fails 3 of 4 on dev, for example expected: <es> but was: <en_GB>.

It's a new class rather than additions to ValidateTest, so it doesn't conflict with #954, which edits that file. Every step of test.yml passed locally (lint, build, PGP check, compose build, Tomcat config check, unit tests, integration tests).

🤖 Generated with Claude Code

…n_GB (#937)

validateLanguage only accepted a session lang matching
".[a-z]{2}-[A-Z]{2}$", but the language picker stores two-letter codes
(es, fr, ...) and translation.jsp stores the request Locale (es_ES), so
it always returned en_GB and every lesson and challenge answered in
English whatever language was picked.

Accept a two-letter language, optionally with a region, and return the
language when it is one the picker offers. Anything else still falls back
to en_GB.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ismisepaul ismisepaul added this to the 4.0.0 milestone Oct 25, 2026
Copilot AI balanced review requested due to automatic review settings October 25, 2026 04:33
@ismisepaul ismisepaul moved this from Backlog to Next Release Backlog in Security Shepherd Oct 25, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

The focused implementation matches the intended language handling and includes appropriate regression coverage, with no unresolved findings.

No open issues 🎉

What changed in this PR

Fixes #937 so lesson and challenge responses use the player’s supported language instead of always falling back to English.

Changes:

  • Accepts picker language codes and normalizes region-qualified values to supported two-letter codes.
  • Preserves the en_GB fallback for missing, unsupported, or malformed values.
  • Adds regression tests in a separate class to avoid overlap with #954.
File Description
src/​test/​java/​utils/​ValidateLanguageTest.java Tests supported codes, locale normalization, and fallback behavior.
src/​main/​java/​utils/​Validate.java Validates and normalizes session languages against the picker’s supported options.

Review effort: Balanced

@ismisepaul ismisepaul added the Needs Manual Testing Must be tested by hand from the PR's branch (steps in the PR) before merging label Oct 25, 2026
Copilot AI balanced review requested due to automatic review settings November 1, 2026 18:51

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

Required running-app checks remain unverified, leaving picker-to-session propagation, translated responses, and missing Spanish/French bundles for a maintainer to validate.

No open issues 🎉

Review effort: Balanced

@ismisepaul ismisepaul mentioned this pull request Nov 1, 2026
15 of 44 tasks

@SeanDuggan SeanDuggan left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I merged this with current dev, and spotless and the full unit suite pass. I also did the manual language check on a running instance, in open-floor mode where RefreshMenu actually calls validateLanguage. English, Español and Français switch correctly. pt works too, and so do es_ES and pt-BR, which reduce to es and pt. Unsupported or malformed values (de, xen-GB) fall back to English. I switched languages with the picker only for English, Español and Français and used ?lang= for the rest.

One thing outside this PR that you may want to follow up on: in incremental-floor mode RefreshMenu and index.jsp pass the raw session lang to Getter.getIncrementalModules, so a regional value like es_ES shows English in that mode.

Copilot AI balanced review requested due to automatic review settings November 9, 2026 13:01

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The manual acceptance steps require Spanish and French SQL Injection responses despite the lesson having only an English bundle, causing false failures and needing correction to use an existing translation.

1 open issue

Review effort: Balanced

if (lang.matches("^[a-z]{2}([_-][A-Za-z]{2})?$")) {
String language = lang.substring(0, 2);
if (SUPPORTED_LANGUAGES.contains(language)) {
result = language;

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Bug Needs Manual Testing Must be tested by hand from the PR's branch (steps in the PR) before merging Platform

Projects

Status: Next Release Backlog

Development

Successfully merging this pull request may close these issues.

Validate.validateLanguage rejects every two-letter language code, so module i18n always falls back to en_GB

3 participants