diff --git a/ui.frontend/src/HTTPAPILayer.js b/ui.frontend/src/HTTPAPILayer.js index 4fdad424ef..b048f7134a 100644 --- a/ui.frontend/src/HTTPAPILayer.js +++ b/ui.frontend/src/HTTPAPILayer.js @@ -66,9 +66,15 @@ class HTTPAPILayer { lang = `${params['afAcceptLang']}` } else { // check for selector in the URL - const parts = window.location.pathname.split('.'); - if (parts?.length >= 3) { - lang = `${parts[parts.length - 2]}`; + const selectorMatch = (window.location.pathname || "").match(/\/([^/]+)\.html(?=\/|$)/); // capture page name prior to .html + if (selectorMatch && selectorMatch.length > 1) { + const parts = selectorMatch[1].split('.'); + if (parts.length >= 2) { + const possibleLocale = parts[parts.length - 1]; + if (Constants.LOCALE_SELECTOR_PATTERN.test(possibleLocale)) { + lang = possibleLocale; + } + } } } // If 'afAcceptLang' is not set and URL selector is not present, use sites page language diff --git a/ui.frontend/src/constants.js b/ui.frontend/src/constants.js index 04d6f8078e..700ecd05ff 100644 --- a/ui.frontend/src/constants.js +++ b/ui.frontend/src/constants.js @@ -374,6 +374,12 @@ export const Constants = { * @memberof module:FormView~Constants * @namespace FIELD_TYPE */ - FIELD_TYPE: FIELD_TYPE + FIELD_TYPE: FIELD_TYPE, + + /** + * Pattern to detect ISO-like locale selectors (e.g., en, en-US, pt_BR). + * @type {RegExp} + */ + LOCALE_SELECTOR_PATTERN: /^[a-z]{2}(?:[-_][a-z0-9]{2,8})?$/i }; diff --git a/ui.tests/test-module/specs/formContainer/formContainer.runtime.cy.js b/ui.tests/test-module/specs/formContainer/formContainer.runtime.cy.js index 6ed3961550..f8960ceed0 100644 --- a/ui.tests/test-module/specs/formContainer/formContainer.runtime.cy.js +++ b/ui.tests/test-module/specs/formContainer/formContainer.runtime.cy.js @@ -116,3 +116,46 @@ describe("Form Runtime with Hamburger Menu", () => { }) +describe("Form Runtime URL handling", () => { + const basePagePath = "content/forms/af/core-components-it/samples/formcontainer/basic.html"; + const formModelEndpoint = "**/guideContainer.model*.json*"; + + const assertFormModelFetch = (formPath) => { + cy.intercept("GET", formModelEndpoint).as("fetchFormModelJson"); + cy.previewForm(formPath).then(container => { + expect(container, `formcontainer is initialized`).to.not.be.null; + const model = typeof container.getModel === "function" ? container.getModel() : container._model; + expect(model, `model is initialized`).to.exist; + }); + cy.wait("@fetchFormModelJson") + .its("response.body") + .should(body => { + expect(body, `response body is available`).to.exist; + }); + }; + + it("fetches form model json without locale selector in URL", () => { + assertFormModelFetch(basePagePath); + }); + + it("fetches form model when .fr locale selector is appended", () => { + const selectorPath = basePagePath.replace(".html", ".fr.html"); + assertFormModelFetch(selectorPath); + }); + + it("fetches form model when .hello.fr selector chain exists", () => { + const selectorPath = basePagePath.replace(".html", ".hello.fr.html"); + assertFormModelFetch(selectorPath); + }); + + it("fetches form model when DAM asset path is appended", () => { + const selectorPath = `${basePagePath}/content/dam/assets/stickers/other/watermark.jpg`; + assertFormModelFetch(selectorPath); + }); + + it("fetches form model when locale selector and asset path exist", () => { + const selectorPath = `${basePagePath.replace(".html", ".fr.html")}/content/dam/assets/stickers/other/watermark.jpg`; + assertFormModelFetch(selectorPath); + }); +}); +