Category: Shopify / Store Locator
Maintained by: Rose Perl Technology
Solution Type: Temporary JavaScript Patch
Status: Active Temporary Solution - Last Updated: 4-3-26
Overview
Some Shopify Store Locator implementations do not currently support Shopify’s native localization system out of the box. To provide immediate multilingual storefront support, Rose Perl Technology released a temporary JavaScript language override patch.
This patch allows Store Locator interface text to change based on the active storefront language without requiring a full backend refactor.
It was released as a temporary workaround while native language support is being developed for a future release.
Important notice
This is a temporary frontend workaround.
Use this patch when:
a store needs multilingual Store Locator support now
native app-level language support is not yet available
the storefront already uses Shopify language routes, locale settings, or language-aware URL patterns
This is not the long-term localization architecture. Once official Store Locator language support is released, this patch should be deprecated and replaced with the native implementation.
What this patch does
The current implementation provides two layers of localization support:
1. SCASLSetting translation override
The script:
detects the active storefront locale
loads the matching translation dictionary
overrides
window.SCASLSettingvalues with translated labelsretries until
SCASLSettingbecomes available
2. DOM label patching
The script also patches selected labels directly in the rendered DOM for cases where some visible Store Locator labels are not controlled by SCASLSetting.
This layer:
applies translations to known DOM-rendered labels
watches the Store Locator container for dynamic re-renders
reapplies translated labels after app redraws or content refreshes
This extra DOM layer is necessary because some labels may be rendered directly by the app and may remain untranslated even after SCASLSetting has been overridden. The original article documented the SCASLSetting-based override and retry behavior; this rewritten version extends the documentation to include the current DOM patching approach as part of the active solution.
Current limitations
This patch has the following limitations:
Only text exposed through
SCASLSettingcan be translated through the settings override layerAny newly introduced Store Locator UI keys must be added manually
Any directly rendered labels must be maintained separately in the DOM patch layer
Some third-party or map-provider-generated controls may still not be translatable
App updates may require the script to be reviewed and updated
This is a frontend override, not a backend localization framework
Future state
Native language support is planned for a future version of the Store Locator tool. When that becomes available, this temporary patch should be considered deprecated and replaced with the official implementation.
Script metadata
/**
* Store Locator Multi-Language Override
* Version: 1.2.0
* Maintained by: Rose Perl Technology
*/
Supported languages
The current script supports the following locales:
Locale | Language |
| English |
| Swedish |
| Norwegian Bokmål |
| German |
| Polish |
| Spanish |
| French |
Locale handling note
The script uses full locale codes for supported storefront languages. It also accepts language-only inputs during detection and maps them to the nearest supported locale where applicable.
Examples:
en→en-gbfr→fr-casv→sv-senborno→nb-node→de-depl→pl-ples→es-es
This allows the patch to work with Shopify locale values, URL paths, query parameters, or HTML lang values that may be supplied in either short or full locale format.
Core configuration
Setting | Value |
Default fallback locale |
|
Supported locales |
|
Retry behavior | Up to 50 retries |
Retry interval | Every 100ms |
Maximum wait time | Approximately 5 seconds |
DOM observation | Enabled |
Script placement | Theme asset, loaded before or alongside Store Locator initialization |
Language detection logic
The script detects locale in the following order of priority:
Priority 1: URL path
Examples:
/en-gb/pages/store-locator/sv-se/pages/store-locator/nb-no/pages/store-locator/de-de/pages/store-locator/pl-pl/pages/store-locator/es-es/pages/store-locator/fr-ca/pages/store-locator
Short language forms may also be resolved where appropriate.
Examples:
/en/pages/store-locator/sv/pages/store-locator/fr/pages/store-locator
Priority 2: URL hash
Examples:
#en-gb#sv-se#fr-ca#fr
Priority 3: URL parameter
Examples:
?lang=en-gb?lang=sv-se?lang=fr-ca?lang=fr
Priority 4: Shopify locale
If present, the script checks:
Shopify.locale
This supports stores where Shopify already exposes the active locale.
Priority 5: HTML lang attribute
The script also checks:
<html lang="de-de">
If no earlier method resolves to a supported locale, the script falls back to English.
The original article documented this general detection order across URL path, hash, query parameter, Shopify locale, and HTML lang.
Default fallback behavior
If no supported language is detected, the script falls back to:
en-gb
This matches the default language behavior documented in the original help article.
How the script applies translations
Once window.SCASLSetting becomes available, the script:
detects the active locale
selects the matching translation dictionary
merges the translated values into
SCASLSetting
If SCASLSetting is not available immediately, the script retries every 100ms for up to 50 attempts.
How the DOM patch layer works
Some visible Store Locator labels may be rendered directly into the DOM instead of being sourced from SCASLSetting. To support those cases, the script includes a separate DOM_LABELS configuration and a DOM patching routine.
The DOM patch layer:
targets known Store Locator label selectors
updates the label text for the active locale
observes the Store Locator container with a
MutationObserverreapplies translations if the UI re-renders dynamically
This is particularly important for app interfaces that redraw panels, hours, or contact sections after initial page load.
DOM labels currently patched
The current DOM patch layer covers the following labels:
DOM label key | Selector | Purpose |
|
| Phone field label |
|
| Email field label |
|
| Hours section label |
These labels should be maintained for every supported locale so directly rendered labels remain consistent with the Store Locator’s translated interface.
Installation
1. Upload the script to Shopify theme assets
Create or upload:
assets/sl-i18n.js
2. Add the script to theme.liquid
Load the script before or alongside the Store Locator script:
<script src="{{ 'sl-i18n.js' | asset_url }}" defer></script>Important loading note
This patch should load early enough that the translation override is ready before or during Store Locator initialization.
Because the script includes retry logic, it can still function if SCASLSetting is injected shortly after page load. Even so, best practice is to load the file before the Store Locator fully initializes.
The original article also required the script to be added to theme assets and loaded before the Store Locator script.
Translation maintenance guidelines
Update TRANSLATIONS when:
the Store Locator app exposes a label through
SCASLSettingan existing translated value needs revision
a new locale is being added
Update DOM_LABELS when:
a visible label does not respond to
SCASLSettinga Store Locator update introduces directly rendered untranslated labels
a supported locale is added or restored
Update DOM selectors when:
the Store Locator app changes element IDs or structure
the existing DOM patch targets no longer match rendered output
Recommended implementation notes
For any store using this patch:
keep
sl-i18n.jsin theme assetsload it before or alongside Store Locator initialization
keep translation keys aligned with current
SCASLSettingkeyskeep DOM label mappings aligned with actual rendered selectors
test all storefront locales after deployment
review the patch after every Store Locator app update
Testing checklist
After deployment, verify:
the correct locale is detected from storefront URLs
the Store Locator loads in the expected language
search labels are translated
no-result messages are translated
map and list controls are translated
operating-hours labels are translated
phone, email, and operating-hours DOM labels remain translated after re-render
English fallback works if no locale is matched
Example localized URL patterns
Locale | Example |
English |
|
Swedish |
|
Norwegian Bokmål |
|
German |
|
Polish |
|
Spanish |
|
French |
|
Shorter inputs may also resolve to supported full locale formats where alias mapping is configured.
Summary
Rose Perl Technology’s Store Locator language override patch is a temporary frontend workaround used to support multilingual Shopify storefronts before native Store Locator language support is available. The original documentation described a settings-based translation override with multi-step locale detection, retry logic, and storefront deployment requirements. The current implementation keeps that behavior and extends it with DOM label patching so directly rendered labels can also remain localized across supported storefront languages.
The current solution:
supports seven locales
detects language through multiple fallback methods
overrides
SCASLSettingpatches selected DOM-rendered labels directly
preserves translations through dynamic re-renders
should remain in use only until official language support is released
This patch should remain in use only until the official language-support release is available.
Appendix: Current Script Reference
Below is the current reference implementation discussed in this article.
/**
* Store Locator Multi-Language Override
* Version: 1.2.0
* Maintained by: Rose Perl Technology
*
* PURPOSE
* -------
* Temporary frontend localization patch for Store Locator when native
* app-level translation support is not yet available.
*
* HOW IT WORKS
* ------------
* 1. Detects locale from storefront signals:
* - URL path
* - URL hash
* - ?lang= query param
* - Shopify.locale
* - <html lang="">
*
* 2. Waits for SCASLSetting to become available, then merges translated
* UI text into that object.
*
* 3. Patches selected labels directly in the DOM because some rendered
* UI text may not come from SCASLSetting.
*
* 4. Observes Store Locator DOM changes so translated labels persist
* after dynamic re-renders.
*
* USAGE NOTES
* -----------
* - Keep this file in Shopify theme assets:
* assets/sl-i18n.js
*
* - Load it in theme.liquid before or alongside Store Locator:
* <script src="{{ 'sl-i18n.js' | asset_url }}" defer></script>
*
* - Add SCASLSetting-driven labels to TRANSLATIONS.
* - Add directly rendered labels to DOM_LABELS and patchDomLabels().
*
* - Review this patch after Store Locator app updates.
*/
(function storeLocatorI18n() {
var DEFAULT_LOCALE = "en-gb";
/**
* Supported locales.
* Short language inputs are mapped to these full locale codes.
*/
var SUPPORTED_LOCALES = [
"en-gb",
"sv-se",
"nb-no",
"de-de",
"pl-pl",
"es-es",
"fr-ca"
];
/**
* Maps short language codes and locale variants to the supported locale.
*/
var LOCALE_ALIASES = {
en: "en-gb",
"en-gb": "en-gb",
"en-us": "en-gb",
"en-ca": "en-gb",
sv: "sv-se",
"sv-se": "sv-se",
nb: "nb-no",
no: "nb-no",
"nb-no": "nb-no",
"no-no": "nb-no",
de: "de-de",
"de-de": "de-de",
pl: "pl-pl",
"pl-pl": "pl-pl",
es: "es-es",
"es-es": "es-es",
fr: "fr-ca",
"fr-ca": "fr-ca",
"fr-fr": "fr-ca",
"fr-be": "fr-ca"
};
/**
* Translation strings merged into SCASLSetting.
* Add new keys here when the Store Locator app exposes them through
* the SCASLSetting configuration object.
*/
var TRANSLATIONS = {
"en-gb": {
page_title: "Store Locator",
curr_loc_text: "Current Location",
enter_a_location_text: "Enter a location",
radius_text: "Search Radius",
msr_text: "Search Radius Measurement",
find_loc_btn_text: "Find My Location",
search_btn_text: "Search",
filter_tags_text: "Filter by Tags",
no_limit_text: "No Limit",
miles_text: "Mile",
kilometers_text: "Kilometer",
kilometer_unit_text: "Kilometer",
map_text: "Map",
list_text: "List",
view_map_btn_text: "View Map",
more_text: "More",
less_text: "Less",
direction_text: "Get Directions",
no_result_title: "No results",
no_result_tags: "No stores found near this location.",
location_is_disabled_alert: "Location Services Disabled",
location_is_disabled_text:
"Please turn on device location to use Find My Location",
open_text: "Open",
open_now_text: "Open now",
opens_text: "Opens",
closed_text: "Closed",
closes_text: "Closes",
closes_soon_text: "Closes soon",
monday_text: "Monday",
tuesday_text: "Tuesday",
wednesday_text: "Wednesday",
thursday_text: "Thursday",
friday_text: "Friday",
saturday_text: "Saturday",
sunday_text: "Sunday",
monday_acronym_text: "Mon",
tuesday_acronym_text: "Tue",
wednesday_acronym_text: "Wed",
thursday_acronym_text: "Thu",
friday_acronym_text: "Fri",
saturday_acronym_text: "Sat",
sunday_acronym_text: "Sun"
},
"fr-ca": {
page_title: "Trouver une boutique",
curr_loc_text: "Emplacement actuel",
enter_a_location_text: "Entrez une adresse",
radius_text: "Rayon de recherche",
msr_text: "Unité de mesure",
find_loc_btn_text: "Me localiser",
search_btn_text: "Rechercher",
filter_tags_text: "Filtrer par tags",
no_limit_text: "Sans limite",
miles_text: "Mille",
kilometers_text: "Kilomètre",
kilometer_unit_text: "Kilomètre",
map_text: "Carte",
list_text: "Liste",
view_map_btn_text: "Voir la carte",
more_text: "Plus",
less_text: "Moins",
direction_text: "Obtenir l'itinéraire",
no_result_title: "Aucun résultat",
no_result_tags: "Aucun magasin trouvé près de cet endroit.",
location_is_disabled_alert: "Services de localisation désactivés",
location_is_disabled_text:
"Veuillez activer la localisation de votre appareil pour utiliser Me localiser",
open_text: "Ouvert",
open_now_text: "Ouvert maintenant",
opens_text: "Ouvre",
closed_text: "Fermé",
closes_text: "Ferme",
closes_soon_text: "Ferme bientôt",
monday_text: "Lundi",
tuesday_text: "Mardi",
wednesday_text: "Mercredi",
thursday_text: "Jeudi",
friday_text: "Vendredi",
saturday_text: "Samedi",
sunday_text: "Dimanche",
monday_acronym_text: "Lun",
tuesday_acronym_text: "Mar",
wednesday_acronym_text: "Mer",
thursday_acronym_text: "Jeu",
friday_acronym_text: "Ven",
saturday_acronym_text: "Sam",
sunday_acronym_text: "Dim"
},
"sv-se": {
page_title: "Butikslokalisering",
curr_loc_text: "Nuvarande plats",
enter_a_location_text: "Ange en plats",
radius_text: "Sökradie",
msr_text: "Måttenhet för sökradie",
find_loc_btn_text: "Hitta min plats",
search_btn_text: "Sök",
filter_tags_text: "Filtrera efter taggar",
no_limit_text: "Ingen gräns",
miles_text: "Mil",
kilometers_text: "Kilometer",
kilometer_unit_text: "Kilometer",
map_text: "Karta",
list_text: "Lista",
view_map_btn_text: "Visa karta",
more_text: "Mer",
less_text: "Mindre",
direction_text: "Få vägbeskrivning",
no_result_title: "Inga resultat",
no_result_tags: "Inga butiker hittades nära denna plats.",
location_is_disabled_alert: "Platstjänster är inaktiverade",
location_is_disabled_text:
"Aktivera enhetens plats för att använda Hitta min plats",
open_text: "Öppet",
open_now_text: "Öppet nu",
opens_text: "Öppnar",
closed_text: "Stängt",
closes_text: "Stänger",
closes_soon_text: "Stänger snart",
monday_text: "Måndag",
tuesday_text: "Tisdag",
wednesday_text: "Onsdag",
thursday_text: "Torsdag",
friday_text: "Fredag",
saturday_text: "Lördag",
sunday_text: "Söndag",
monday_acronym_text: "Mån",
tuesday_acronym_text: "Tis",
wednesday_acronym_text: "Ons",
thursday_acronym_text: "Tor",
friday_acronym_text: "Fre",
saturday_acronym_text: "Lör",
sunday_acronym_text: "Sön"
},
"nb-no": {
page_title: "Butikklokalisering",
curr_loc_text: "Nåværende posisjon",
enter_a_location_text: "Skriv inn et sted",
radius_text: "Søkeradius",
msr_text: "Måleenhet for søkeradius",
find_loc_btn_text: "Finn min posisjon",
search_btn_text: "Søk",
filter_tags_text: "Filtrer etter tagger",
no_limit_text: "Ingen grense",
miles_text: "Mil",
kilometers_text: "Kilometer",
kilometer_unit_text: "Kilometer",
map_text: "Kart",
list_text: "Liste",
view_map_btn_text: "Vis kart",
more_text: "Mer",
less_text: "Mindre",
direction_text: "Få veibeskrivelse",
no_result_title: "Ingen resultater",
no_result_tags: "Ingen butikker ble funnet nær dette stedet.",
location_is_disabled_alert: "Posisjonstjenester deaktivert",
location_is_disabled_text:
"Slå på enhetens posisjon for å bruke Finn min posisjon",
open_text: "Åpen",
open_now_text: "Åpen nå",
opens_text: "Åpner",
closed_text: "Stengt",
closes_text: "Stenger",
closes_soon_text: "Stenger snart",
monday_text: "Mandag",
tuesday_text: "Tirsdag",
wednesday_text: "Onsdag",
thursday_text: "Torsdag",
friday_text: "Fredag",
saturday_text: "Lørdag",
sunday_text: "Søndag",
monday_acronym_text: "Man",
tuesday_acronym_text: "Tir",
wednesday_acronym_text: "Ons",
thursday_acronym_text: "Tor",
friday_acronym_text: "Fre",
saturday_acronym_text: "Lør",
sunday_acronym_text: "Søn"
},
"de-de": {
page_title: "Filialsuche",
curr_loc_text: "Aktueller Standort",
enter_a_location_text: "Ort eingeben",
radius_text: "Suchradius",
msr_text: "Einheit für Suchradius",
find_loc_btn_text: "Meinen Standort finden",
search_btn_text: "Suchen",
filter_tags_text: "Nach Tags filtern",
no_limit_text: "Keine Begrenzung",
miles_text: "Meile",
kilometers_text: "Kilometer",
kilometer_unit_text: "Kilometer",
map_text: "Karte",
list_text: "Liste",
view_map_btn_text: "Karte anzeigen",
more_text: "Mehr",
less_text: "Weniger",
direction_text: "Route anzeigen",
no_result_title: "Keine Ergebnisse",
no_result_tags: "Keine Geschäfte in der Nähe dieses Ortes gefunden.",
location_is_disabled_alert: "Standortdienste deaktiviert",
location_is_disabled_text:
"Bitte aktivieren Sie den Standort Ihres Geräts, um Meinen Standort finden zu verwenden",
open_text: "Geöffnet",
open_now_text: "Jetzt geöffnet",
opens_text: "Öffnet",
closed_text: "Geschlossen",
closes_text: "Schließt",
closes_soon_text: "Schließt bald",
monday_text: "Montag",
tuesday_text: "Dienstag",
wednesday_text: "Mittwoch",
thursday_text: "Donnerstag",
friday_text: "Freitag",
saturday_text: "Samstag",
sunday_text: "Sonntag",
monday_acronym_text: "Mo",
tuesday_acronym_text: "Di",
wednesday_acronym_text: "Mi",
thursday_acronym_text: "Do",
friday_acronym_text: "Fr",
saturday_acronym_text: "Sa",
sunday_acronym_text: "So"
},
"pl-pl": {
page_title: "Lokalizator sklepów",
curr_loc_text: "Bieżąca lokalizacja",
enter_a_location_text: "Wpisz lokalizację",
radius_text: "Promień wyszukiwania",
msr_text: "Jednostka promienia wyszukiwania",
find_loc_btn_text: "Znajdź moją lokalizację",
search_btn_text: "Szukaj",
filter_tags_text: "Filtruj według tagów",
no_limit_text: "Bez limitu",
miles_text: "Mila",
kilometers_text: "Kilometr",
kilometer_unit_text: "Kilometr",
map_text: "Mapa",
list_text: "Lista",
view_map_btn_text: "Pokaż mapę",
more_text: "Więcej",
less_text: "Mniej",
direction_text: "Wyznacz trasę",
no_result_title: "Brak wyników",
no_result_tags: "Nie znaleziono sklepów w pobliżu tej lokalizacji.",
location_is_disabled_alert: "Usługi lokalizacji wyłączone",
location_is_disabled_text:
"Włącz lokalizację urządzenia, aby użyć opcji Znajdź moją lokalizację",
open_text: "Otwarte",
open_now_text: "Otwarte teraz",
opens_text: "Otwiera",
closed_text: "Zamknięte",
closes_text: "Zamyka",
closes_soon_text: "Wkrótce zamyka",
monday_text: "Poniedziałek",
tuesday_text: "Wtorek",
wednesday_text: "Środa",
thursday_text: "Czwartek",
friday_text: "Piątek",
saturday_text: "Sobota",
sunday_text: "Niedziela",
monday_acronym_text: "Pon",
tuesday_acronym_text: "Wt",
wednesday_acronym_text: "Śr",
thursday_acronym_text: "Czw",
friday_acronym_text: "Pt",
saturday_acronym_text: "Sob",
sunday_acronym_text: "Nd"
},
"es-es": {
page_title: "Localizador de tiendas",
curr_loc_text: "Ubicación actual",
enter_a_location_text: "Introduce una ubicación",
radius_text: "Radio de búsqueda",
msr_text: "Unidad de medida del radio",
find_loc_btn_text: "Encontrar mi ubicación",
search_btn_text: "Buscar",
filter_tags_text: "Filtrar por etiquetas",
no_limit_text: "Sin límite",
miles_text: "Milla",
kilometers_text: "Kilómetro",
kilometer_unit_text: "Kilómetro",
map_text: "Mapa",
list_text: "Lista",
view_map_btn_text: "Ver mapa",
more_text: "Más",
less_text: "Menos",
direction_text: "Obtener indicaciones",
no_result_title: "Sin resultados",
no_result_tags: "No se encontraron tiendas cerca de esta ubicación.",
location_is_disabled_alert: "Servicios de ubicación desactivados",
location_is_disabled_text:
"Activa la ubicación del dispositivo para usar Encontrar mi ubicación",
open_text: "Abierto",
open_now_text: "Abierto ahora",
opens_text: "Abre",
closed_text: "Cerrado",
closes_text: "Cierra",
closes_soon_text: "Cierra pronto",
monday_text: "Lunes",
tuesday_text: "Martes",
wednesday_text: "Miércoles",
thursday_text: "Jueves",
friday_text: "Viernes",
saturday_text: "Sábado",
sunday_text: "Domingo",
monday_acronym_text: "Lun",
tuesday_acronym_text: "Mar",
wednesday_acronym_text: "Mié",
thursday_acronym_text: "Jue",
friday_acronym_text: "Vie",
saturday_acronym_text: "Sáb",
sunday_acronym_text: "Dom"
}
};
/**
* Labels patched directly into the rendered DOM.
* Add entries here when visible labels are not controlled by SCASLSetting.
*/
var DOM_LABELS = {
"en-gb": {
phone_label: "Phone Number",
email_label: "Email",
operating_hours_label: "Operating Hours"
},
"fr-ca": {
phone_label: "Numéro de téléphone",
email_label: "Courriel",
operating_hours_label: "Heures d'ouverture"
},
"sv-se": {
phone_label: "Telefonnummer",
email_label: "E-post",
operating_hours_label: "Öppettider"
},
"nb-no": {
phone_label: "Telefonnummer",
email_label: "E-post",
operating_hours_label: "Åpningstider"
},
"de-de": {
phone_label: "Telefonnummer",
email_label: "E-Mail",
operating_hours_label: "Öffnungszeiten"
},
"pl-pl": {
phone_label: "Numer telefonu",
email_label: "E-mail",
operating_hours_label: "Godziny otwarcia"
},
"es-es": {
phone_label: "Número de teléfono",
email_label: "Correo electrónico",
operating_hours_label: "Horario de atención"
}
};
function normalizeLocale(input) {
if (!input) return null;
var normalized = String(input).toLowerCase().trim();
return LOCALE_ALIASES[normalized] || null;
}
function localeFromPath(pathname) {
var match = pathname.match(/^\/([a-z]{2}(?:-[a-z]{2})?)(\/|$)/i);
return match ? normalizeLocale(match[1]) : null;
}
function localeFromHash(hash) {
var cleaned = String(hash || "").replace(/^#/, "");
return normalizeLocale(cleaned);
}
function localeFromQuery(search) {
var params = new URLSearchParams(search);
return normalizeLocale(params.get("lang"));
}
function localeFromShopify() {
return typeof Shopify !== "undefined" && Shopify.locale
? normalizeLocale(Shopify.locale)
: null;
}
function localeFromHtmlLang() {
var htmlLang = document.documentElement.lang || "";
return normalizeLocale(htmlLang);
}
/**
* Detect the active locale using multiple storefront signals.
* Falls back to DEFAULT_LOCALE if no supported value is found.
*/
function detectLocale() {
return (
localeFromPath(window.location.pathname) ||
localeFromHash(window.location.hash) ||
localeFromQuery(window.location.search) ||
localeFromShopify() ||
localeFromHtmlLang() ||
DEFAULT_LOCALE
);
}
/**
* Merge locale strings into SCASLSetting.
*/
function applyTranslations(translations) {
if (typeof window.SCASLSetting === "undefined") {
return false;
}
Object.assign(window.SCASLSetting, translations);
return true;
}
/**
* Patch directly rendered DOM labels.
* Update selectors here if Store Locator markup changes.
*/
function patchDomLabels(labels) {
if (!labels) return;
if (labels.phone_label) {
document.querySelectorAll("#scasl-phone-label").forEach(function (el) {
if (el.textContent !== labels.phone_label) {
el.textContent = labels.phone_label;
}
});
}
if (labels.email_label) {
document.querySelectorAll("#scasl-email-label").forEach(function (el) {
if (el.textContent !== labels.email_label) {
el.textContent = labels.email_label;
}
});
}
if (labels.operating_hours_label) {
document
.querySelectorAll("#scasl-operating-hours-label")
.forEach(function (el) {
if (el.textContent !== labels.operating_hours_label) {
el.textContent = labels.operating_hours_label;
}
});
}
}
/**
* Observe Store Locator DOM changes so translated labels persist after re-renders.
*/
function observeDom(labels) {
var container =
document.querySelector("#scasl-app-container") || document.body;
var observer = new MutationObserver(function () {
patchDomLabels(labels);
});
observer.observe(container, {
childList: true,
subtree: true
});
patchDomLabels(labels);
}
/**
* Initialize localization flow.
*/
function init() {
var locale = detectLocale();
var translations = TRANSLATIONS[locale] || TRANSLATIONS[DEFAULT_LOCALE];
var domLabels = DOM_LABELS[locale] || DOM_LABELS[DEFAULT_LOCALE];
var attempts = 0;
var interval = setInterval(function () {
attempts++;
if (applyTranslations(translations)) {
clearInterval(interval);
return;
}
if (attempts >= 50) {
clearInterval(interval);
console.warn(
"[sl-i18n] SCASLSetting not found after 50 attempts. Patch not applied."
);
}
}, 100);
observeDom(domLabels);
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", init);
} else {
init();
}
})();
