diff --git a/scripts/aem.js b/scripts/aem.js index 40662e6148..e8f446c548 100644 --- a/scripts/aem.js +++ b/scripts/aem.js @@ -499,34 +499,35 @@ function decorateSections(main) { */ // eslint-disable-next-line import/prefer-default-export async function fetchPlaceholders(prefix = 'default') { + if (window.placeholders?.[prefix]) return window.placeholders[prefix]; + window.placeholders = window.placeholders || {}; - if (!window.placeholders[prefix]) { - window.placeholders[prefix] = new Promise((resolve) => { - fetch(`${prefix === 'default' ? '' : prefix}/placeholders.json`) - .then((resp) => { - if (resp.ok) { - return resp.json(); - } - return {}; - }) - .then((json) => { - const placeholders = {}; - json.data - .filter((placeholder) => placeholder.Key) - .forEach((placeholder) => { - placeholders[toCamelCase(placeholder.Key)] = placeholder.Text; - }); - window.placeholders[prefix] = placeholders; - resolve(window.placeholders[prefix]); - }) - .catch(() => { - // error loading placeholders - window.placeholders[prefix] = {}; - resolve(window.placeholders[prefix]); - }); + + try { + const response = await fetch(`${prefix === 'default' ? '' : prefix}/placeholders.json`); + const json = response.ok ? await response.json() : { data: [] }; + + // Transform data into nested structure + const placeholders = {}; + json.data.forEach(({ Key, Value }) => { + if (Key) { + const keys = Key.split('.'); + const lastKey = keys.pop(); + const target = keys.reduce((obj, key) => { + obj[key] = obj[key] || {}; + return obj[key]; + }, placeholders); + target[lastKey] = Value; + } }); + + // Cache and return result + window.placeholders[prefix] = placeholders; + } catch (error) { + window.placeholders[prefix] = {}; // Set empty object on error } - return window.placeholders[`${prefix}`]; + + return window.placeholders[prefix]; } /** diff --git a/scripts/initializers/account.js b/scripts/initializers/account.js index 4275de07fa..fe93cd5a6c 100644 --- a/scripts/initializers/account.js +++ b/scripts/initializers/account.js @@ -1,7 +1,16 @@ import { initializers } from '@dropins/tools/initializer.js'; import { initialize } from '@dropins/storefront-account/api.js'; import { initializeDropin } from './index.js'; +import { fetchPlaceholders } from '../aem.js'; initializeDropin(async () => { - await initializers.mountImmediately(initialize, {}); + const labels = await fetchPlaceholders(); + + const langDefinitions = { + default: { + ...labels, + }, + }; + + await initializers.mountImmediately(initialize, { langDefinitions }); })(); diff --git a/scripts/initializers/auth.js b/scripts/initializers/auth.js index 26ab9fd989..8e155db934 100644 --- a/scripts/initializers/auth.js +++ b/scripts/initializers/auth.js @@ -2,7 +2,16 @@ import { initializers } from '@dropins/tools/initializer.js'; import { initialize } from '@dropins/storefront-auth/api.js'; import { initializeDropin } from './index.js'; +import { fetchPlaceholders } from '../aem.js'; initializeDropin(async () => { - await initializers.mountImmediately(initialize, {}); + const labels = await fetchPlaceholders(); + + const langDefinitions = { + default: { + ...labels, + }, + }; + + await initializers.mountImmediately(initialize, { langDefinitions }); })(); diff --git a/scripts/initializers/cart.js b/scripts/initializers/cart.js index e31f636f53..530b10f3f5 100644 --- a/scripts/initializers/cart.js +++ b/scripts/initializers/cart.js @@ -2,7 +2,16 @@ import { initializers } from '@dropins/tools/initializer.js'; import { initialize } from '@dropins/storefront-cart/api.js'; import { initializeDropin } from './index.js'; +import { fetchPlaceholders } from '../aem.js'; initializeDropin(async () => { - await initializers.mountImmediately(initialize, {}); + const labels = await fetchPlaceholders(); + + const langDefinitions = { + default: { + ...labels, + }, + }; + + await initializers.mountImmediately(initialize, { langDefinitions }); })(); diff --git a/scripts/initializers/checkout.js b/scripts/initializers/checkout.js index c264870d72..b332a5e654 100644 --- a/scripts/initializers/checkout.js +++ b/scripts/initializers/checkout.js @@ -1,7 +1,16 @@ import { initializers } from '@dropins/tools/initializer.js'; import { initialize } from '@dropins/storefront-checkout/api.js'; import { initializeDropin } from './index.js'; +import { fetchPlaceholders } from '../aem.js'; initializeDropin(async () => { - await initializers.mountImmediately(initialize, {}); + const labels = await fetchPlaceholders(); + + const langDefinitions = { + default: { + ...labels, + }, + }; + + await initializers.mountImmediately(initialize, { langDefinitions }); })(); diff --git a/scripts/initializers/order-confirmation.js b/scripts/initializers/order-confirmation.js index 2a9e3fa416..fa8d748392 100644 --- a/scripts/initializers/order-confirmation.js +++ b/scripts/initializers/order-confirmation.js @@ -1,7 +1,16 @@ import { initializers } from '@dropins/tools/initializer.js'; import { initialize } from '@dropins/storefront-order-confirmation/api.js'; import { initializeDropin } from './index.js'; +import { fetchPlaceholders } from '../aem.js'; initializeDropin(async () => { - await initializers.mountImmediately(initialize, {}); + const labels = await fetchPlaceholders(); + + const langDefinitions = { + default: { + ...labels, + }, + }; + + await initializers.mountImmediately(initialize, { langDefinitions }); })(); diff --git a/scripts/initializers/order.js b/scripts/initializers/order.js index eb9dd0b014..0b64e87dcb 100644 --- a/scripts/initializers/order.js +++ b/scripts/initializers/order.js @@ -3,6 +3,7 @@ import { initializers } from '@dropins/tools/initializer.js'; import { initialize } from '@dropins/storefront-order/api.js'; import { checkIsAuthenticated } from '../configs.js'; import { initializeDropin } from './index.js'; +import { fetchPlaceholders } from '../aem.js'; import { CUSTOMER_ORDER_DETAILS_PATH, @@ -25,6 +26,14 @@ initializeDropin(async () => { })(); async function handleUserOrdersRedirects(pathname, isAccountPage, orderRef, isTokenProvided) { + const labels = await fetchPlaceholders(); + + const langDefinitions = { + default: { + ...labels, + }, + }; + let targetPath = null; if (pathname.includes(CUSTOMER_ORDERS_PATH)) { return; @@ -60,6 +69,7 @@ async function handleUserOrdersRedirects(pathname, isAccountPage, orderRef, isTo window.location.href = targetPath; } else { await initializers.mountImmediately(initialize, { + langDefinitions, orderRef, }); } diff --git a/scripts/initializers/pdp.js b/scripts/initializers/pdp.js index b8fc38f5dd..53fc8a621a 100644 --- a/scripts/initializers/pdp.js +++ b/scripts/initializers/pdp.js @@ -23,46 +23,16 @@ await initializeDropin(async () => { const sku = getSkuFromUrl(); window.getProductPromise = getProduct(sku); - const [product, placeholders] = await Promise.all([ + const [product, labels] = await Promise.all([ window.getProductPromise, fetchPlaceholders(), ]); const langDefinitions = { default: { - PDP: { - Product: { - Incrementer: { label: placeholders.pdpProductIncrementer }, - OutOfStock: { label: placeholders.pdpProductOutofstock }, - AddToCart: { label: placeholders.pdpProductAddtocart }, - Details: { label: placeholders.pdpProductDetails }, - RegularPrice: { label: placeholders.pdpProductRegularprice }, - SpecialPrice: { label: placeholders.pdpProductSpecialprice }, - PriceRange: { - From: { label: placeholders.pdpProductPricerangeFrom }, - To: { label: placeholders.pdpProductPricerangeTo }, - }, - Image: { label: placeholders.pdpProductImage }, - }, - Swatches: { - Required: { label: placeholders.pdpSwatchesRequired }, - }, - Carousel: { - label: placeholders.pdpCarousel, - Next: { label: placeholders.pdpCarouselNext }, - Previous: { label: placeholders.pdpCarouselPrevious }, - Slide: { label: placeholders.pdpCarouselSlide }, - Controls: { - label: placeholders.pdpCarouselControls, - Button: { label: placeholders.pdpCarouselControlsButton }, - }, - }, - Overlay: { - Close: { label: placeholders.pdpOverlayClose }, - }, - }, + ...labels, Custom: { - AddingToCart: { label: placeholders.pdpCustomAddingtocart }, + AddingToCart: { label: labels.pdpCustomAddingtocart }, }, }, };