diff --git a/application/example/i18n/providers/embed.mjs b/application/example/i18n/providers/embed.mjs
index 52912ff1a24444d0a8678586f078fcc0d0a0d899..652669adef0d678a4abab9faf72f0889a5069c80 100644
--- a/application/example/i18n/providers/embed.mjs
+++ b/application/example/i18n/providers/embed.mjs
@@ -1,5 +1,5 @@
 import {Embed} from '@schukai/monster/source/i18n/providers/embed.mjs';
 
-// read from scritp tag with id i18n
+// read from script tag with id i18n
 const translation = new Embed('i18n');
 
diff --git a/application/source/dom/customelement.mjs b/application/source/dom/customelement.mjs
index 0cccfb1b2ffb8159d0f27e1a2590c483f7b4ac9a..3b991a412732c12d627db5afbe8fd418c23ac0ea 100644
--- a/application/source/dom/customelement.mjs
+++ b/application/source/dom/customelement.mjs
@@ -295,25 +295,45 @@ class CustomElement extends HTMLElement {
      * Before you can use this method, you must have loaded the translations.
      *
      * @returns {Monster.DOM.CustomElement}
+     * @throws {Error}  Cannot find element with translations. Add a translations object to the document.
      */
     updateI18n() {
-
         const translations = getDocumentTranslations();
         if (!translations) {
             return this;
         }
 
-        const labels = this.getOption("labels");
-        if (!isIterable(labels)) {
+        let labels = this.getOption("labels");
+        if (!(isObject(labels) || isIterable(labels))) {
             return this;
         }
 
         for (const key in labels) {
-            const text = translations.getText(key, labels[key]);
-            if (text !== labels[key]) {
-                this.setOption("labels." + key, text);
+            const def = labels[key];
+
+            if (isString(def)) {
+                const text = translations.getText(key, def);
+                if (text !== def) {
+                    this.setOption("labels." + key, text);
+                }
+                continue;
+            } else if (isObject(def)) {
+                for (const k in def) {
+                    const d = def[k];
+                    
+                    const text = translations.getPluralRuleText(key, k, d);
+                    if (!isString(text)) {
+                        throw new Error("Invalid labels definition");
+                    }
+                    if (text !== d) {
+                        this.setOption("labels." + key + "." + k, text);
+                    }
+                }
+                continue;
             }
 
+            throw new Error("Invalid labels definition");
+
         }
         return this;
     }
@@ -973,10 +993,10 @@ function registerCustomElement(element) {
     if (customElements === undefined) {
         throw new Error("customElements is not supported.");
     }
-    
+
     if (customElements.get(element.getTag()) !== undefined) {
         return;
     }
-    
+
     customElements.define(element.getTag(), element);
 }
diff --git a/application/source/i18n/translations.mjs b/application/source/i18n/translations.mjs
index 8d6836938266c993ab706ee0802f54787955bfa8..a575d87dadc6984ad0d108367222f85a4c33fed8 100644
--- a/application/source/i18n/translations.mjs
+++ b/application/source/i18n/translations.mjs
@@ -104,7 +104,7 @@ class Translations extends Base {
         } else {
             count = validateInteger(count);
             if (count === 0) {
-                // special handlig for zero count
+                // special handling for zero count
                 if (r.hasOwnProperty("zero")) {
                     return validateString(r["zero"]);
                 }
diff --git a/development/playground/i18n-control/index.html b/development/playground/i18n-control/index.html
new file mode 100644
index 0000000000000000000000000000000000000000..5113abe71aa55e92771ec8c7f8407fb15d811f9e
--- /dev/null
+++ b/development/playground/i18n-control/index.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <script type="module" src="main.mjs"></script>
+</head>
+<body>
+<h1>Updater</h1>
+
+<script type="application/json" data-monster-role="translations">
+    {
+        "theListContainsNoEntries": "translation1",
+        "key2": {
+            "other": "translation2"
+        },
+        "multi": {
+            "two": "translation3"
+        }
+    }
+</script>
+
+<monster-1>Monster1</monster-1>
+
+</body>
+</html>
diff --git a/development/playground/i18n-control/main.mjs b/development/playground/i18n-control/main.mjs
new file mode 100644
index 0000000000000000000000000000000000000000..7bfa80beb59562ea05af688c961ce184a06c472e
--- /dev/null
+++ b/development/playground/i18n-control/main.mjs
@@ -0,0 +1,76 @@
+import {Fetch} from '../../../application/source/i18n/providers/fetch.mjs';
+import {Updater} from '../../../application/source/dom/updater.mjs';
+import {CustomElement, registerCustomElement} from '../../../application/source/dom/customelement.mjs';
+import {domReady} from '../../../application/source/dom/ready.mjs';
+import {Embed} from '../../../application/source/i18n/providers/embed.mjs';
+
+
+class Monster1 extends CustomElement {
+
+
+    get defaults() {
+        return Object.assign(
+            {},
+            super.defaults,
+            {
+                labels: {
+                    theListContainsNoEntries: "The list contains no entries",
+                    multi: {
+                        zero: "Zero",
+                        one: "One",
+                        two: "Two",
+                        few: "Few",
+                        many: "Many",
+                        other: "Other"
+                        
+                    }
+                }
+            });
+    };
+
+    /**
+     *
+     * @return {string}
+     */
+    static getTag() {
+        return "monster-1";
+    }
+
+}
+
+
+domReady.then(() => {
+
+    Embed.assignTranslationsToElement().then(() => {
+        m1.updateI18n();
+        console.log(m1.getOption('labels'));
+        console.log(m1.getOption('labels.multi.two'));
+    });
+
+    const translation = new Embed('i18n');
+    const m1 = document.querySelector("monster-1");
+
+
+// read from scritp tag with id i18n
+
+
+});
+
+registerCustomElement(Monster1);
+
+//
+// const provider = new Fetch('translation.json', {
+//     method: 'GET',
+//     headers: {
+//         'Content-Type': 'application/json',
+//     },
+// });
+//
+// provider
+//     .assignToElement()
+//     .then(() => {
+//         new Updater(document.body, {}).run();
+//     })
+//     .catch((e) => {
+//         console.error(e);
+//     });
diff --git a/development/playground/i18n-control/translation.json b/development/playground/i18n-control/translation.json
new file mode 100644
index 0000000000000000000000000000000000000000..88b3d7123ad3385ca8ae033933b77a3bb4efbe42
--- /dev/null
+++ b/development/playground/i18n-control/translation.json
@@ -0,0 +1,4 @@
+{
+  "key1": "value1",
+  "key2": "value2"
+}
\ No newline at end of file