diff --git a/source/dom/customelement.mjs b/source/dom/customelement.mjs
index c4e2fcc4c52fad9f8695782778769d8cd8ce6f9c..69b7287874f6e50ead17fe29983a0a49c7757a8b 100644
--- a/source/dom/customelement.mjs
+++ b/source/dom/customelement.mjs
@@ -297,6 +297,7 @@ class CustomElement extends HTMLElement {
 	 * @property {Object} templateFormatter.marker Specifies the marker for the templates.
 	 * @property {Function} templateFormatter.marker.open=null Specifies the opening marker for the templates.
 	 * @property {Function} templateFormatter.marker.close=null Specifies the closing marker for the templates.
+	 * @property {Boolean} templateFormatter.i18n=false Specifies whether the templates should be formatted with i18n.
 	 * @property {Boolean} eventProcessing=false Specifies whether the control processes events.
 	 * @since 1.8.0
 	 */
@@ -314,6 +315,7 @@ class CustomElement extends HTMLElement {
 					open: null,
 					close: null,
 				},
+				i18n : false,
 			},
 
 			eventProcessing: false,
@@ -1075,6 +1077,27 @@ function parseOptionsJSON(data) {
 	return validateObject(obj);
 }
 
+/**
+ * @private
+ * @param html
+ * @returns {*|string}
+ */
+function substituteI18n(html) {
+
+	if(!this.getOption("templateFormatter.i18n", false)) {
+		return html;
+	}
+
+	const labels = this.getOption("labels", {});
+	if (!(isObject(labels) || isIterable(labels))) {
+		return html;
+	}
+
+	const formatter = new Formatter(labels, {});
+	formatter.setMarker("i18n{", '}')
+	return formatter.format(html);
+}
+
 /**
  * @private
  * @return {initHtmlContent}
@@ -1090,7 +1113,7 @@ function initHtmlContent() {
 			if (isObject(mapping)) {
 				html = new Formatter(mapping, {}).format(html);
 			}
-			this.innerHTML = html;
+			this.innerHTML = substituteI18n.call(this, html);
 		}
 	}
 
@@ -1194,7 +1217,7 @@ function initShadowRoot() {
 		html = formatter.format(html);
 	}
 
-	this.shadowRoot.innerHTML = html;
+	this.shadowRoot.innerHTML = substituteI18n.call(this, html);
 	return this;
 }
 
diff --git a/test/cases/components/form/button.mjs b/test/cases/components/form/button.mjs
index 07292a08d45bfe4020a7a75a3ec89c5d379b8cff..652e3edc3faf6b8aa2b1b6ea3842b4cd914602c8 100644
--- a/test/cases/components/form/button.mjs
+++ b/test/cases/components/form/button.mjs
@@ -38,13 +38,12 @@ describe('Button', function () {
     before(function (done) {
         initJSDOM().then(() => {
 
-            import("element-internals-polyfill").catch(e => done(e));
-
-            import("../../../../source/components/form/button.mjs").then((m) => {
-                Button = m['Button'];
-                done()
-            }).catch(e => done(e))
-
+            import("element-internals-polyfill").then(()=>{
+                import("../../../../source/components/form/button.mjs").then((m) => {
+                    Button = m['Button'];
+                    done()
+                }).catch(e => done(e))
+            }).catch(e => done(e));
 
         });
     })
diff --git a/test/util/jsdom.mjs b/test/util/jsdom.mjs
index 747f8618c9a4955bec0efc9c973cbefeab17f4b7..0153d3ce56902c008505e2df7098208df80bea52 100644
--- a/test/util/jsdom.mjs
+++ b/test/util/jsdom.mjs
@@ -67,7 +67,7 @@ function initJSDOM(options) {
                     'InputEvent',
                     'KeyboardEvent',
                     'MutationObserver',
-                    'navigator',
+                //    'navigator',
                     'Node',
                     'NodeFilter',
                     'NodeList',
@@ -76,7 +76,9 @@ function initJSDOM(options) {
                     'XMLSerializer',
                 ].forEach(key => {
                     try {
-                        g[key] = window[key]    
+                        console.log("setting key", key);
+
+                        g[key] = window[key]
                     } catch(e) {
                         console.error("Error setting key", key, e);
                     }